js實(shí)現(xiàn)拖動(dòng)緩動(dòng)效果
話(huà)不多說(shuō),先上效果,一個(gè)體驗(yàn)非常好的拖拽緩動(dòng)的效果,讓頁(yè)面提升一個(gè)檔次。

這個(gè)效果看似很簡(jiǎn)單,到也困惑了很長(zhǎng)時(shí)間,為什么別人寫(xiě)出來(lái)的拖拽體驗(yàn)為什么這么好?
直到我自己實(shí)現(xiàn)了以后,才發(fā)現(xiàn),原來(lái)我想的實(shí)現(xiàn)方式不對(duì)。接下來(lái),我通過(guò)簡(jiǎn)短的幾句話(huà),來(lái)提供這個(gè)功能的實(shí)現(xiàn)思路。
首先,我們要明白,我們鼠標(biāo)拖拽是在一個(gè)2d平面上拖拽
2d平面只有x軸和y軸,而且獲取的拖拽值也是基于平面的像素獲取的。所以,我們第一步,先通過(guò)鼠標(biāo)事件來(lái)獲取到當(dāng)前的拖拽的長(zhǎng)度像素。
首先,綁定鼠標(biāo)按下事件,來(lái)獲取到鼠標(biāo)基于瀏覽器窗口左上角的xy平面二維坐標(biāo)。
然后,綁定move事件,在move事件回調(diào)內(nèi)獲取到鼠標(biāo)拖拽的坐標(biāo),和按下坐標(biāo)相減,求出拖拽的距離。
然后,我們需要通過(guò)一定比例,將拖拽的像素轉(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)來(lái)了,如何實(shí)現(xiàn)惰性旋轉(zhuǎn)呢?
通過(guò)上面思路,我們知道了目標(biāo)角度,那么直接設(shè)置目標(biāo)角度,肯定就沒(méi)有這種想要的效果了,那么如何實(shí)現(xiàn)這種惰性效果呢?
接下來(lái),我們需要一個(gè)專(zhuān)門(mén)實(shí)現(xiàn)動(dòng)畫(huà)的requestAnimationFrame方法,這個(gè)方法是閑時(shí)運(yùn)行,最大根據(jù)性能能夠達(dá)到60幀每秒,有好多小伙伴感覺(jué)一直遞歸運(yùn)行會(huì)不會(huì)卡頓,或者影響性能。那是你多慮了,這個(gè)方法會(huì)根據(jù)當(dāng)前頁(yè)面性能進(jìn)行減幀,保證頁(yè)面流暢運(yùn)行。
我們有了這個(gè)以后,然后做什么呢,就是用來(lái)實(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是通過(guò)css3d來(lái)實(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)畫(huà)的導(dǎo)航欄效果
- 讓div運(yùn)動(dòng)起來(lái) 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)畫(huà)
- JavaScript實(shí)現(xiàn)緩動(dòng)動(dòng)畫(huà)
- JavaScript緩動(dòng)動(dòng)畫(huà)函數(shù)的封裝方法
相關(guān)文章
使用JavaScript實(shí)現(xiàn)ajax的實(shí)例代碼
實(shí)現(xiàn)ajax之前必須要?jiǎng)?chuàng)建一個(gè) XMLHttpRequest 對(duì)象。這是必須的。那么對(duì)使用js實(shí)現(xiàn)ajax的代碼感興趣的朋友可以參考下本文2016-05-05
JavaScript簡(jiǎn)單實(shí)現(xiàn)合并兩個(gè)Json對(duì)象的方法示例
這篇文章主要介紹了JavaScript簡(jiǎn)單實(shí)現(xiàn)合并兩個(gè)Json對(duì)象的方法,結(jié)合實(shí)例形式分析了json對(duì)象的遍歷、添加實(shí)現(xiàn)合并的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
JavaScript Event學(xué)習(xí)第四章 傳統(tǒng)的事件注冊(cè)模型
在這一章我會(huì)講解給元素注冊(cè)事件的最好的一種辦法,那就是:確保一個(gè)特定的事件在特定的HTML元素上發(fā)生并且能運(yùn)行特定的腳本。2010-02-02
小程序hover-class點(diǎn)擊態(tài)效果實(shí)現(xiàn)
這篇文章主要介紹了小程序hover-class點(diǎn)擊態(tài)效果實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
JavaScript基礎(chǔ)入門(mén)之錯(cuò)誤捕獲機(jī)制
初級(jí)開(kāi)發(fā)人員往往很少使用js的拋出和捕獲異常,但拋出和捕獲異常往往是非常必要的,這篇文章主要給大家介紹了關(guān)于JavaScript基礎(chǔ)入門(mén)之錯(cuò)誤捕獲機(jī)制的相關(guān)資料,需要的朋友可以參考下2021-08-08
JavaScript+html5 canvas繪制的小人效果
這篇文章主要介紹了JavaScript+html5 canvas繪制的小人效果,涉及JavaScript結(jié)合html5 canvas圖形繪制及顏色隨機(jī)填充的技巧,需要的朋友可以參考下2016-01-01

