JS隨拖拽速度設(shè)置傾斜角度的實(shí)現(xiàn)代碼

拖拽速度設(shè)置傾斜角度
實(shí)現(xiàn)
求拖拽速度設(shè)置傾斜角度,就是求速度與角度之間的關(guān)系。

∵ ( 角度 / 最大角度 ) = ( 速度 / 最大速度 ) * 固定系數(shù)
∴ 角度 = ( 速度 / 最大速度 ) / 最大角度 * 固定系數(shù)
這里的固定系數(shù)其實(shí)是旋轉(zhuǎn)系數(shù),用于調(diào)整旋轉(zhuǎn)幅度。它是一個(gè)乘法因子,允許你根據(jù)需要增加或減小旋轉(zhuǎn)的幅度。 好處就是自定義旋轉(zhuǎn)幅度,可以在不改變速度和最大旋轉(zhuǎn)角度的情況下,根據(jù)具體場景的需要自定義旋轉(zhuǎn)幅度。
上面的公式非常清楚了,接下來就是編寫 Code 求出速度就行。因?yàn)樽畲笏俣?、最大角度、固定系?shù)都是固定的。
而計(jì)算速度的方式就很簡單了,路程除以時(shí)間。
而在拖拽過程中,路程就是兩次觸發(fā)拖拽的時(shí)候的差值,時(shí)間就直接 performance.now() 。所以計(jì)算速度的方法如下:
// eslint-disable-next-line prefer-const
let lastX = x.value
// eslint-disable-next-line prefer-const
let startTime = performance.now()
function calVelocity(lastX: number, currentX: number, lastTime: number, currentTime = performance.now()) {
const distanceX = currentX - lastX
const deltaTime = currentTime - lastTime
return {
velocity: distanceX / deltaTime,
newTime: currentTime,
newX: currentX,
}
}當(dāng)拖拽的時(shí)候,觸發(fā) calVelocity() , 然后將最新的 newTime 和 newX 賦值給 startTime 和 lastX 就行了。
以上就是核心代碼邏輯,下面有首圖的 ts 代碼,不過使用了 Vue 框架和 VueUse 、VueUse/motion工具類。如果想要跑通,需要配置一下。
// 1. 具有兩個(gè)動(dòng)畫,一個(gè)是上下浮動(dòng),一個(gè)是拖拽的時(shí)候會(huì)有小幅度旋轉(zhuǎn)
// 2. 拖拽的時(shí)候,根據(jù)速度計(jì)算旋轉(zhuǎn)幅度,這個(gè)時(shí)候上下浮動(dòng)消失
// 3. 拖拽結(jié)束后(速度小于一個(gè)閾值或者鼠標(biāo)抬起或者鼠標(biāo)移動(dòng)到了外面),旋轉(zhuǎn)幅度取消,上下浮動(dòng)重新開始
/** ************************設(shè)置拖拽和旋轉(zhuǎn)***************************** */
const props = defineProps({
initialPosition: {
default: () => ({
x: Math.random() * (window.innerWidth - 400),
y: Math.random() * (window.innerHeight - 160),
}),
},
})
const target = ref<HTMLElement>()
const { apply: waveApply } = useMotion(target, {
initial: { rotate: 0 },
enter: { rotate: 0 },
})
async function setRotate(rotate: number) {
await waveApply({
rotate,
})
}
const { x, style, isDragging } = useDraggable(target, { initialValue: props.initialPosition })
let rotationDelta = 0
watch(isDragging, async () => {
if (isDragging.value) {
// 拖拽的時(shí)候,取消上下浮動(dòng)
}
else {
// 拖拽結(jié)束后,設(shè)置旋轉(zhuǎn)角度為 0 , 恢復(fù)上下浮動(dòng)
setRotate(0)
rotationDelta = 0
}
})
/** **************************************************************** */
/** ************************通過速度計(jì)算旋轉(zhuǎn)幅度***************************** */
let lastX = x.value
let startTime = performance.now()
// 當(dāng)前角度 / 當(dāng)前速度 = 最大角度 / 最大速度
// 得出:當(dāng)前角度 = ( 最大角度 / 最大速度 ) * 當(dāng)前速度
// 然后再乘以一個(gè)系數(shù),用于調(diào)整旋轉(zhuǎn)幅度,角度跟速度的比例
const cfg = {
maxVelocity: 10, // 最大速度
maxRotation: 60, // 最大旋轉(zhuǎn)角度
rotationFactor: 0.8, // 旋轉(zhuǎn)系數(shù),用于調(diào)整旋轉(zhuǎn)幅度
}
watch(x, () => {
const { velocity, newX, newTime } = calVelocity(lastX, x.value, startTime)
const { maxVelocity, maxRotation, rotationFactor } = cfg
// 速度除以最大速度,將速度歸一化為一個(gè)介于 0 和 1 之間的小數(shù)值,表示速度相對(duì)于最大速度的比例。
// 將這個(gè)比例值乘以最大旋轉(zhuǎn)角度 maxRotation,這樣就得到了基于速度的旋轉(zhuǎn)角度
// 但這得出的仍是一個(gè)相對(duì)值,最后,再將這個(gè)相對(duì)的旋轉(zhuǎn)角度乘以旋轉(zhuǎn)系數(shù) rotationFactor,以調(diào)整最終的旋轉(zhuǎn)幅度。
rotationDelta = -(velocity / maxVelocity * maxRotation * rotationFactor)
setRotate(rotationDelta)
lastX = newX
startTime = newTime
})
function calVelocity(lastX: number, currentX: number, lastTime: number, currentTime = performance.now()) {
const distanceX = currentX - lastX
const deltaTime = currentTime - lastTime
return {
velocity: distanceX / deltaTime,
newTime: currentTime,
newX: currentX,
}
}
/** **************************************************************** */以上就是JS隨拖拽速度設(shè)置傾斜角度的實(shí)現(xiàn)代碼的詳細(xì)內(nèi)容,更多關(guān)于JS設(shè)置傾斜角度的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
bootstrap datetimepicker2.3.11時(shí)間插件使用
這篇文章主要為大家詳細(xì)介紹了bootstrap datetimepicker2.3.11時(shí)間插件使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
釘釘小程序web-view內(nèi)嵌H5頁面并實(shí)現(xiàn)通信
本文主要介紹了釘釘小程序web-view內(nèi)嵌H5頁面并實(shí)現(xiàn)通信,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
通過JS動(dòng)態(tài)創(chuàng)建一個(gè)html DOM元素并顯示
需要通過點(diǎn)擊某個(gè)元素后, 動(dòng)態(tài)創(chuàng)建一個(gè)DOM元素并顯示,因此寫了一些相關(guān)的js函數(shù),在此記錄下2014-10-10
原生js實(shí)現(xiàn)ajax請(qǐng)求和JSONP跨域請(qǐng)求操作示例
這篇文章主要介紹了原生js實(shí)現(xiàn)ajax請(qǐng)求和JSONP跨域請(qǐng)求操作,結(jié)合實(shí)例形式分析了基于原生js實(shí)現(xiàn)的ajax請(qǐng)求和JSONP跨域請(qǐng)求相關(guān)操作技巧與使用注意事項(xiàng),需要的朋友可以參考下2020-03-03
js+css實(shí)現(xiàn)扇形導(dǎo)航效果
這篇文章主要為大家詳細(xì)介紹了js+css實(shí)現(xiàn)扇形導(dǎo)航效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
JavaScript閉包_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了JavaScript閉包,閉包(closure)是Javascript語言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)2017-06-06
基于layui的table插件進(jìn)行復(fù)選框聯(lián)動(dòng)功能的實(shí)現(xiàn)方法
今天小編就為大家分享一篇基于layui的table插件進(jìn)行復(fù)選框聯(lián)動(dòng)功能的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09
layer.prompt使文本框?yàn)榭盏那闆r下也能點(diǎn)擊確定的方法
今天小編就為大家分享一篇layer.prompt使文本框?yàn)榭盏那闆r下也能點(diǎn)擊確定的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09

