拋物線運動就是:當拖拽結束的時候,我們讓當前的元素同時水平運動+垂直運動 在同樣的移動距離下,我們滑鼠移動的速度快,move方法觸發的次數少,相反移動的速度慢,move方法觸發的次數就多->瀏覽器對於每一次的move行為的觸發都是由一個最小時間的 通過觀察,我們發現一個事情:水平方向我們盒子在結束拖 ...
拋物線運動就是:當拖拽結束的時候,我們讓當前的元素同時水平運動+垂直運動
在同樣的移動距離下,我們滑鼠移動的速度快,move方法觸發的次數少,相反移動的速度慢,move方法觸發的次數就多->瀏覽器對於每一次的move行為的觸發都是由一個最小時間的
通過觀察,我們發現一個事情:水平方向我們盒子在結束拖拽的時候移動的速度和移動的距離沒有必然的聯繫,和開始拖拽的速度也沒有必然的聯繫,只和最後一次即將鬆開的那一瞬間滑鼠的速度是有關係的,最後瞬間滑鼠如果移動的快,我們水平運動的距離和速度也是比較大的。->獲取滑鼠最後一次即將鬆開時候的速度。
在JS盒子模型中,offsetLeft是獲取當前元素的左偏移,獲取到的值永遠不會出現小數, 他會把真實的left值按照小數點的四捨五入進行計算
具體代碼如下:
<!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實現讓當前的元素在屏幕居中的位置 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"; //拖拽的原理 /* 當滑鼠在盒子上按下的時候,我們開始拖拽(給盒子綁定onmousemove和onmouseup),當滑鼠移動的時候,我們計算盒子的最新位置 當滑鼠抬起的時候說明拖拽結束了,我們的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()//把當前的滑鼠和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); }; } //當盒子運動中我們想要執行下一次拖拽,我們按下滑鼠,但是由於盒子還是運動著呢,導致滑鼠抓不住盒子->在按下的同時我們應該停止盒子的運動 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"; //計算我們水平方向移動的速度 /* 在瀏覽器最小反應時間內觸發一次move,我們都記錄一下當前盒子的位置,讓當前的位置-上一次記錄的位置=當前最後一次的偏移 */ 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();//把當前的滑鼠和盒子解除綁定 this.onmousemove = null; this.onmouseup= null; }else{ document.onmousemove = null; document.onmouseup= null; //這樣綁定的話,move和up綁定的this都是document } //當滑鼠離開結束拖拽的時候,我們開始進行水平方向的動畫運動 fly.call(this); //當滑鼠離開結束拖拽的時候,我們開始進行垂直方向的動畫運動 drop.call(this); } //當滑鼠移動過快的時候,我們的滑鼠會脫離盒子,導致盒子的mousemove和mouseup事件都移除不到->"滑鼠焦點丟失" //在IE和火狐瀏覽器中,我們用一個方法把盒子和滑鼠綁定在一起即可。 //滑鼠再快也跑不出去文檔:我們把mousemove和mouseup綁定給document function fly(){ //this->當前要操作的盒子 var _this = this; _this.flyTimer = window.setInterval(function(){ //我們運動的速度是一直在減慢的,一直到停止("指數衰減運動") //this->window //盒子停止運動,清除定時器:利用offsetLeft獲取的值不會出現小數,對小數部分進行了四捨五入,所以我們加上或者減去一個小於0.5的速度值,其實對於盒子本身的位置並沒有發生實質的改變,我們認為此階段的盒子就停止運動了。 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>