js彈性勢能動畫之拋物線運動實例詳解
拋物線運動就是:當(dāng)拖拽結(jié)束的時候,我們讓當(dāng)前的元素同時水平運動+垂直運動
在同樣的移動距離下,我們鼠標移動的速度快,move方法觸發(fā)的次數(shù)少,相反移動的速度慢,move方法觸發(fā)的次數(shù)就多->瀏覽器對于每一次的move行為的觸發(fā)都是由一個最小時間的。
通過觀察,我們發(fā)現(xiàn)一個事情:水平方向我們盒子在結(jié)束拖拽的時候移動的速度和移動的距離沒有必然的聯(lián)系,和開始拖拽的速度也沒有必然的聯(lián)系,只和最后一次即將松開的那一瞬間鼠標的速度是有關(guān)系的,最后瞬間鼠標如果移動的快,我們水平運動的距離和速度也是比較大的。->獲取鼠標最后一次即將松開時候的速度。
在JS盒子模型中,offsetLeft是獲取當(dāng)前元素的左偏移,獲取到的值永遠不會出現(xiàn)小數(shù), 他會把真實的left值按照小數(shù)點的四舍五入進行計算
具體代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin:0; padding:0; } html,body{ width:100%; height:100%; } #box{ position:absolute; top:50%; left:50%; width:200px; height:200px; background:#ff6600; margin:-100px 0 0 -100px; cursor:move; /* 不知道寬高的情況下的居中 position:absolute; top:0; left:0; right:0; bottom:0; margin:auto; */ } </style> </head> <body> <div id='box'> </div> <script> //JS實現(xiàn)讓當(dāng)前的元素在屏幕居中的位置 var box = document.getElementById('box'); // box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight)-box.offsetHeight)/2 + "px"; // box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 + "px"; //拖拽的原理 /* 當(dāng)鼠標在盒子上按下的時候,我們開始拖拽(給盒子綁定onmousemove和onmouseup),當(dāng)鼠標移動的時候,我們計算盒子的最新位置 當(dāng)鼠標抬起的時候說明拖拽結(jié)束了,我們的move和up就沒用了,我們再把這兩個方法移除 */ box.onmousedown = down; function down(e){ e = e || window.event; //記錄開始位置的信息 this["strX"] = e.clientX; this["strY"] = e.clientY; this["strL"] = parseFloat(this.style.left); this["strT"] = parseFloat(this.style.top); //給元素綁定移動和抬起的事件 if(this.setCapture){ this.setCapture()//把當(dāng)前的鼠標和this綁定在一起 this.onmousemove = move; this.onmouseup= up; }else{ var _this = this; document.onmousemove = function(e){ // move(e)//這個里面的this是window move.call(_this,e); } ; document.onmouseup= function(e){ up.call(_this,e); }; } //當(dāng)盒子運動中我們想要執(zhí)行下一次拖拽,我們按下鼠標,但是由于盒子還是運動著呢,導(dǎo)致鼠標抓不住盒子->在按下的同時我們應(yīng)該停止盒子的運動 window.clearInterval(this.flyTimer); window.clearInterval(this.dropTimer); } function move(e){ e = e || window.event; var curL = (e.clientX-this["strX"])+this["strL"]; var curT = (e.clientY-this["strY"])+this["strT"]; //邊界判斷 var minL = 0,minT = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth,maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight; curL = curL < minL ? minL :(curL > maxL ? maxL : curL); curT = curT < minT ? minT :(curT > maxT ? maxT : curT) this.style.left = curL + "px"; this.style.top = curT + "px"; //計算我們水平方向移動的速度 /* 在瀏覽器最小反應(yīng)時間內(nèi)觸發(fā)一次move,我們都記錄一下當(dāng)前盒子的位置,讓當(dāng)前的位置-上一次記錄的位置=當(dāng)前最后一次的偏移 */ if(!this.pre){ this.pre = this.offsetLeft; }else{ this.speedFly = this.offsetLeft - this.pre; this.pre = this.offsetLeft; } } function up(e){ if(this.releaseCapture){ this.releaseCapture();//把當(dāng)前的鼠標和盒子解除綁定 this.onmousemove = null; this.onmouseup= null; }else{ document.onmousemove = null; document.onmouseup= null; //這樣綁定的話,move和up綁定的this都是document } //當(dāng)鼠標離開結(jié)束拖拽的時候,我們開始進行水平方向的動畫運動 fly.call(this); //當(dāng)鼠標離開結(jié)束拖拽的時候,我們開始進行垂直方向的動畫運動 drop.call(this); } //當(dāng)鼠標移動過快的時候,我們的鼠標會脫離盒子,導(dǎo)致盒子的mousemove和mouseup事件都移除不到->"鼠標焦點丟失" //在IE和火狐瀏覽器中,我們用一個方法把盒子和鼠標綁定在一起即可。 //鼠標再快也跑不出去文檔:我們把mousemove和mouseup綁定給document function fly(){ //this->當(dāng)前要操作的盒子 var _this = this; _this.flyTimer = window.setInterval(function(){ //我們運動的速度是一直在減慢的,一直到停止("指數(shù)衰減運動") //this->window //盒子停止運動,清除定時器:利用offsetLeft獲取的值不會出現(xiàn)小數(shù),對小數(shù)部分進行了四舍五入,所以我們加上或者減去一個小于0.5的速度值,其實對于盒子本身的位置并沒有發(fā)生實質(zhì)的改變,我們認為此階段的盒子就停止運動了。 if(Math.abs(_this.speedFly)<0.5){ window.clearInterval(_this.flyTimer); return; } _this.speedFly*=0.98; var curL = _this.offsetLeft + _this.speedFly; var minL = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - _this.offsetWidth; if(curL>=maxL){ _this.style.left = maxL + "px"; _this.speedFly*=-1; }else if(curL<=minL){ _this.style.left = minL + "px"; _this.speedFly*=-1; }else{ _this.style.left = curL; } },10) } function drop(){ var _this = this; _this.dragFlag = 0; _this.dropTimer = window.setInterval(function(){ if(_this.dragFlag>1){//到底的時候dragFlag就大于1了 window.clearInterval(_this.dropTimer); return; } _this.dropSpeed = !_this.dropSpeed ? 9.8 : _this.dropSpeed + 9.8; //衰減 _this.dropSpeed*=0.98; var curT = _this.offsetTop + _this.dropSpeed; var maxT = (document.documentElement.clientHeight || document.body.clientHeight) - _this.offsetHeight; if(curT >= maxT){// 到底了 _this.style.top = maxT + "px"; _this.dropSpeed*=-1; _this.dragFlag++; }else{ _this.style.top = curT + "px"; _this.dragFlag = 0; } }) } </script> </body> </html>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript使用setTimeout實現(xiàn)倒計時效果
這篇文章主要為大家詳細介紹了JavaScript使用setTimeout實現(xiàn)倒計時效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-02-02JS使用隊列對數(shù)組排列,基數(shù)排序算法示例
這篇文章主要介紹了JS使用隊列對數(shù)組排列,基數(shù)排序算法,涉及javascript隊列的定義、使用,基數(shù)排序?qū)崿F(xiàn)方法等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03在iFrame子頁面里實現(xiàn)模態(tài)框的方法
今天小編就為大家分享一篇在iFrame子頁面里實現(xiàn)模態(tài)框的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08Javascript類型轉(zhuǎn)換的規(guī)則實例解析
這篇文章主要介紹了Javascript類型轉(zhuǎn)換的規(guī)則實例解析,涉及到j(luò)avascript類型轉(zhuǎn)換相關(guān)知識,對本文感興趣的朋友一起學(xué)習(xí)吧2016-02-02向大師們學(xué)習(xí)Javascript(視頻與PPT)
在開始之前,先與大家一起認識下這篇文章的主角,世界級的javascript大牛們:Douglas Crockford、John Resig、Peter-Paul Koch、Nicolas C. Zakas??疵忠苍S挺陌生,但是如果你對javascript還算熟悉,一定不會對他們的作品陌生。2009-12-12layer彈窗在鍵盤按回車將反復(fù)刷新的實現(xiàn)方法
今天小編就為大家分享一篇layer彈窗在鍵盤按回車將反復(fù)刷新的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09JS獲取今天是本月第幾周、本月共幾周、本月有多少天、是今年的第幾周、是今年的第幾天的示例代碼
這篇文章主要介紹了JS獲取今天是本月第幾周、本月共幾周、本月有多少天、是今年的第幾周、是今年的第幾天,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2018-12-12微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面
本文主要介紹了微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12