js彈性勢(shì)能動(dòng)畫之拋物線運(yùn)動(dòng)實(shí)例詳解
拋物線運(yùn)動(dòng)就是:當(dāng)拖拽結(jié)束的時(shí)候,我們讓當(dāng)前的元素同時(shí)水平運(yùn)動(dòng)+垂直運(yùn)動(dòng)
在同樣的移動(dòng)距離下,我們鼠標(biāo)移動(dòng)的速度快,move方法觸發(fā)的次數(shù)少,相反移動(dòng)的速度慢,move方法觸發(fā)的次數(shù)就多->瀏覽器對(duì)于每一次的move行為的觸發(fā)都是由一個(gè)最小時(shí)間的。
通過觀察,我們發(fā)現(xiàn)一個(gè)事情:水平方向我們盒子在結(jié)束拖拽的時(shí)候移動(dòng)的速度和移動(dòng)的距離沒有必然的聯(lián)系,和開始拖拽的速度也沒有必然的聯(lián)系,只和最后一次即將松開的那一瞬間鼠標(biāo)的速度是有關(guān)系的,最后瞬間鼠標(biāo)如果移動(dòng)的快,我們水平運(yùn)動(dòng)的距離和速度也是比較大的。->獲取鼠標(biāo)最后一次即將松開時(shí)候的速度。
在JS盒子模型中,offsetLeft是獲取當(dāng)前元素的左偏移,獲取到的值永遠(yuǎn)不會(huì)出現(xiàn)小數(shù), 他會(huì)把真實(shí)的left值按照小數(shù)點(diǎn)的四舍五入進(jìn)行計(jì)算
具體代碼如下:
<!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實(shí)現(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)鼠標(biāo)在盒子上按下的時(shí)候,我們開始拖拽(給盒子綁定onmousemove和onmouseup),當(dāng)鼠標(biāo)移動(dòng)的時(shí)候,我們計(jì)算盒子的最新位置 當(dāng)鼠標(biāo)抬起的時(shí)候說明拖拽結(jié)束了,我們的move和up就沒用了,我們?cè)侔堰@兩個(gè)方法移除 */ 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); //給元素綁定移動(dòng)和抬起的事件 if(this.setCapture){ this.setCapture()//把當(dāng)前的鼠標(biāo)和this綁定在一起 this.onmousemove = move; this.onmouseup= up; }else{ var _this = this; document.onmousemove = function(e){ // move(e)//這個(gè)里面的this是window move.call(_this,e); } ; document.onmouseup= function(e){ up.call(_this,e); }; } //當(dāng)盒子運(yùn)動(dòng)中我們想要執(zhí)行下一次拖拽,我們按下鼠標(biāo),但是由于盒子還是運(yùn)動(dòng)著呢,導(dǎo)致鼠標(biāo)抓不住盒子->在按下的同時(shí)我們應(yīng)該停止盒子的運(yùn)動(dò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"; //計(jì)算我們水平方向移動(dòng)的速度 /* 在瀏覽器最小反應(yīng)時(shí)間內(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)前的鼠標(biāo)和盒子解除綁定 this.onmousemove = null; this.onmouseup= null; }else{ document.onmousemove = null; document.onmouseup= null; //這樣綁定的話,move和up綁定的this都是document } //當(dāng)鼠標(biāo)離開結(jié)束拖拽的時(shí)候,我們開始進(jìn)行水平方向的動(dòng)畫運(yùn)動(dòng) fly.call(this); //當(dāng)鼠標(biāo)離開結(jié)束拖拽的時(shí)候,我們開始進(jìn)行垂直方向的動(dòng)畫運(yùn)動(dòng) drop.call(this); } //當(dāng)鼠標(biāo)移動(dòng)過快的時(shí)候,我們的鼠標(biāo)會(huì)脫離盒子,導(dǎo)致盒子的mousemove和mouseup事件都移除不到->"鼠標(biāo)焦點(diǎn)丟失" //在IE和火狐瀏覽器中,我們用一個(gè)方法把盒子和鼠標(biāo)綁定在一起即可。 //鼠標(biāo)再快也跑不出去文檔:我們把mousemove和mouseup綁定給document function fly(){ //this->當(dāng)前要操作的盒子 var _this = this; _this.flyTimer = window.setInterval(function(){ //我們運(yùn)動(dòng)的速度是一直在減慢的,一直到停止("指數(shù)衰減運(yùn)動(dòng)") //this->window //盒子停止運(yùn)動(dòng),清除定時(shí)器:利用offsetLeft獲取的值不會(huì)出現(xiàn)小數(shù),對(duì)小數(shù)部分進(jìn)行了四舍五入,所以我們加上或者減去一個(gè)小于0.5的速度值,其實(shí)對(duì)于盒子本身的位置并沒有發(fā)生實(shí)質(zhì)的改變,我們認(rèn)為此階段的盒子就停止運(yùn)動(dòng)了。 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){//到底的時(shí)候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)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript使用setTimeout實(shí)現(xiàn)倒計(jì)時(shí)效果
這篇文章主要為大家詳細(xì)介紹了JavaScript使用setTimeout實(shí)現(xiàn)倒計(jì)時(shí)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02JS使用隊(duì)列對(duì)數(shù)組排列,基數(shù)排序算法示例
這篇文章主要介紹了JS使用隊(duì)列對(duì)數(shù)組排列,基數(shù)排序算法,涉及javascript隊(duì)列的定義、使用,基數(shù)排序?qū)崿F(xiàn)方法等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03在iFrame子頁面里實(shí)現(xiàn)模態(tài)框的方法
今天小編就為大家分享一篇在iFrame子頁面里實(shí)現(xiàn)模態(tài)框的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08Javascript類型轉(zhuǎn)換的規(guī)則實(shí)例解析
這篇文章主要介紹了Javascript類型轉(zhuǎn)換的規(guī)則實(shí)例解析,涉及到j(luò)avascript類型轉(zhuǎn)換相關(guān)知識(shí),對(duì)本文感興趣的朋友一起學(xué)習(xí)吧2016-02-02向大師們學(xué)習(xí)Javascript(視頻與PPT)
在開始之前,先與大家一起認(rèn)識(shí)下這篇文章的主角,世界級(jí)的javascript大牛們:Douglas Crockford、John Resig、Peter-Paul Koch、Nicolas C. Zakas??疵忠苍S挺陌生,但是如果你對(duì)javascript還算熟悉,一定不會(huì)對(duì)他們的作品陌生。2009-12-12layer彈窗在鍵盤按回車將反復(fù)刷新的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layer彈窗在鍵盤按回車將反復(fù)刷新的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09JS獲取今天是本月第幾周、本月共幾周、本月有多少天、是今年的第幾周、是今年的第幾天的示例代碼
這篇文章主要介紹了JS獲取今天是本月第幾周、本月共幾周、本月有多少天、是今年的第幾周、是今年的第幾天,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-12-12微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面
本文主要介紹了微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12