js實(shí)現(xiàn)拖動(dòng)緩動(dòng)效果
話不多說,先上效果,一個(gè)體驗(yàn)非常好的拖拽緩動(dòng)的效果,讓頁(yè)面提升一個(gè)檔次。
這個(gè)效果看似很簡(jiǎn)單,到也困惑了很長(zhǎng)時(shí)間,為什么別人寫出來的拖拽體驗(yàn)為什么這么好?
直到我自己實(shí)現(xiàn)了以后,才發(fā)現(xiàn),原來我想的實(shí)現(xiàn)方式不對(duì)。接下來,我通過簡(jiǎn)短的幾句話,來提供這個(gè)功能的實(shí)現(xiàn)思路。
首先,我們要明白,我們鼠標(biāo)拖拽是在一個(gè)2d平面上拖拽
2d平面只有x軸和y軸,而且獲取的拖拽值也是基于平面的像素獲取的。所以,我們第一步,先通過鼠標(biāo)事件來獲取到當(dāng)前的拖拽的長(zhǎng)度像素。
首先,綁定鼠標(biāo)按下事件,來獲取到鼠標(biāo)基于瀏覽器窗口左上角的xy平面二維坐標(biāo)。
然后,綁定move事件,在move事件回調(diào)內(nèi)獲取到鼠標(biāo)拖拽的坐標(biāo),和按下坐標(biāo)相減,求出拖拽的距離。
然后,我們需要通過一定比例,將拖拽的像素轉(zhuǎn)換為旋轉(zhuǎn)角度
我這里設(shè)置的比例是,
鼠標(biāo)橫向拖拽10像素,那模型沿3d的Y軸坐標(biāo)就旋轉(zhuǎn)5度,
鼠標(biāo)縱向拖拽10像素,模型沿3d世界的X軸坐標(biāo)旋轉(zhuǎn)1度,并且還設(shè)置了范圍,即沿x軸旋轉(zhuǎn)再-45度到45度之間
function onDocumentMouseMove(event) { mouseX = event.clientX; mouseY = event.clientY; targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDownX) * 0.5; targetRotationY = Math.min(Math.max((targetRotationOnMouseDownY - (mouseY - mouseXOnMouseDownY) * 0.1), -45), 45); //拖拽后的目標(biāo)位置 }
上面獲取到目標(biāo)角度,重點(diǎn)來了,如何實(shí)現(xiàn)惰性旋轉(zhuǎn)呢?
通過上面思路,我們知道了目標(biāo)角度,那么直接設(shè)置目標(biāo)角度,肯定就沒有這種想要的效果了,那么如何實(shí)現(xiàn)這種惰性效果呢?
接下來,我們需要一個(gè)專門實(shí)現(xiàn)動(dòng)畫的requestAnimationFrame方法,這個(gè)方法是閑時(shí)運(yùn)行,最大根據(jù)性能能夠達(dá)到60幀每秒,有好多小伙伴感覺一直遞歸運(yùn)行會(huì)不會(huì)卡頓,或者影響性能。那是你多慮了,這個(gè)方法會(huì)根據(jù)當(dāng)前頁(yè)面性能進(jìn)行減幀,保證頁(yè)面流暢運(yùn)行。
我們有了這個(gè)以后,然后做什么呢,就是用來實(shí)現(xiàn)緩動(dòng),在每一幀里面,獲取到目標(biāo)角度和當(dāng)前角度的角度差,然后每一次只選擇總進(jìn)度的百分之10 ,然后你會(huì)發(fā)現(xiàn)選擇離目標(biāo)角度越近,越慢,體驗(yàn)效果也是非常的棒。
而且在運(yùn)行中,角度也會(huì)無(wú)限制的接近目標(biāo)角度,當(dāng)前demo是通過css3d來實(shí)現(xiàn)的:
function animate() { requestAnimationFrame(animate); rotateY += (targetRotationX - rotateY) * 0.1; rotateX += (targetRotationY - rotateX) * 0.1; box.style.transform = 'rotateY(' + rotateY + 'deg)'; item.style.transform = 'rotateX(' + rotateX + 'deg)'; }
案例全部代碼
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>css3d翻轉(zhuǎn)</title> <style> * { padding: 0; margin: 0; } body { display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; perspective: 1000px; } .item { width: 50vw; height: 50vh; transform: rotateX(-50deg); perspective: 5000px; transform-style: preserve-3d; } .box { background: #abb9c5; width: 100%; height: 100%; transform-style: preserve-3d; position: relative; } .font, .back { position: absolute; top: 0; left: 0; width: 100%; height: 100%; text-align: center; line-height: 50vh; background: #4cae4c; backface-visibility: hidden; } .back { background: #62ebff; transform: rotateY(180deg); } </style> </head> <body> <!--item 可以觸發(fā)翻轉(zhuǎn)的區(qū)域--> <div class="item"> <!--box 可以翻轉(zhuǎn)的容器--> <div class="box"> <!--font 默認(rèn)顯示的正面--> <div class="font">正面</div> <!--back 背面--> <div class="back">背面</div> </div> </div> </body> <script> var targetRotationX = 0; var targetRotationY = 0; var targetRotationOnMouseDownX = 0; var targetRotationOnMouseDownY = 0; var mouseX = 0; var mouseY = 0; var mouseXOnMouseDownX = 0; var mouseXOnMouseDownY = 0; var box = document.querySelector('.box'); var item = document.querySelector('.item'); var rotateY = 0; var rotateX = 0; init(); animate(); function init() { // EVENTS document.addEventListener('mousedown', onDocumentMouseDown, false); document.addEventListener('touchstart', onDocumentTouchStart, false); document.addEventListener('touchmove', onDocumentTouchMove, false); } function onDocumentMouseDown(event) { event.preventDefault(); document.addEventListener('mousemove', onDocumentMouseMove, false); document.addEventListener('mouseup', onDocumentMouseUp, false); mouseXOnMouseDownX = event.clientX; mouseXOnMouseDownY = event.clientY; targetRotationOnMouseDownX = targetRotationX; targetRotationOnMouseDownY = targetRotationY; } function onDocumentMouseMove(event) { mouseX = event.clientX; mouseY = event.clientY; targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDownX) * 0.5; targetRotationY = Math.min(Math.max((targetRotationOnMouseDownY - (mouseY - mouseXOnMouseDownY) * 0.1), -45), 45); //拖拽后的目標(biāo)位置 } function onDocumentMouseUp() { document.removeEventListener('mousemove', onDocumentMouseMove, false); document.removeEventListener('mouseup', onDocumentMouseUp, false); } function onDocumentTouchStart(event) { event.preventDefault(); if (event.touches.length === 1) { mouseXOnMouseDownX = event.touches[0].pageX; mouseXOnMouseDownY = event.touches[0].pageY; targetRotationOnMouseDownX = targetRotationX; targetRotationOnMouseDownY = targetRotationY; } } function onDocumentTouchMove(event) { event.preventDefault(); if (event.touches.length === 1) { mouseX = event.touches[0].pageX; mouseY = event.touches[0].pageY; targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDownX) * 0.5; targetRotationY = Math.min(Math.max((targetRotationOnMouseDownY - (mouseY - mouseXOnMouseDownY) * 0.1), -45), 45); //拖拽后的目標(biāo)位置 } } function animate() { requestAnimationFrame(animate); rotateY += (targetRotationX - rotateY) * 0.1; rotateX += (targetRotationY - rotateX) * 0.1; box.style.transform = 'rotateY(' + rotateY + 'deg)'; item.style.transform = 'rotateX(' + rotateX + 'deg)'; } </script> </html>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- javascript 45種緩動(dòng)效果 非???/a>
- js實(shí)現(xiàn)帶緩動(dòng)動(dòng)畫的導(dǎo)航欄效果
- 讓div運(yùn)動(dòng)起來 js實(shí)現(xiàn)緩動(dòng)效果
- JS輪播圖中緩動(dòng)函數(shù)的封裝
- javascript簡(jiǎn)易緩動(dòng)插件(源碼打包)
- JS實(shí)現(xiàn)可用滑塊滑動(dòng)的緩動(dòng)圖代碼
- tweenjs緩動(dòng)算法的使用實(shí)例分析
- js實(shí)現(xiàn)緩動(dòng)動(dòng)畫
- JavaScript實(shí)現(xiàn)緩動(dòng)動(dòng)畫
- JavaScript緩動(dòng)動(dòng)畫函數(shù)的封裝方法
相關(guān)文章
淺聊一下Javascript中的數(shù)據(jù)類型和類型轉(zhuǎn)換
在JavaScript中,理解數(shù)據(jù)類型,如何區(qū)分它們,以及它們?nèi)绾伪晦D(zhuǎn)換是至關(guān)重要的,在這篇文章中,我們將探討這些主題,以幫助大家鞏固JavaScript基礎(chǔ)2023-08-08javascript數(shù)組元素刪除方法delete和splice解析
這篇文章主要介紹了javascaipt數(shù)組元素刪除方法delete和splice解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12BootStrap daterangepicker 雙日歷控件
這篇文章主要介紹了BootStrap daterangepicker 雙日歷控件,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06webpack3升級(jí)到webpack4遇到問題總結(jié)
這篇文章主要介紹了webpack3升級(jí)到webpack4遇到問題總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09js 距離某一時(shí)間點(diǎn)時(shí)間是多少實(shí)現(xiàn)代碼
距離某一時(shí)間點(diǎn)時(shí)間是多少,在本文將為大家介紹下js中是如何實(shí)現(xiàn)的,感興趣的朋友不要錯(cuò)過2013-10-10詳解全棧開發(fā)Vercel數(shù)據(jù)庫(kù)存儲(chǔ)服務(wù)
這篇文章主要為大家介紹了全棧開發(fā)Vercel數(shù)據(jù)庫(kù)存儲(chǔ)服務(wù)功能使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05