我有一个应用程序,希望用户能够在屏幕上投掷/轻弹对象。从本质上讲,他们会在屏幕上快速拖动元素并松开,然后它会以相同的速度沿着拖动的方向继续移动,然后减速直到停止。
任何语言或伪代码的答案都将不胜感激。或者,如果这个算法有一个名字,你可以给我指一下,那也会很有帮助。感谢
我会找到鼠标移动的速度,并将对象的速度设置为鼠标的速度。对象速度=鼠标速度然后每刻度降低该速度,直到达到0。
如果你想让它更逼真,我会看看这里:https://physics.stackexchange.com/questions/391318/how-to-calculate-a-change-in-velocity-as-a-result-of-friction
这是我的尝试:
- 用户在时间
t1
开始在位置(x1, y1)
拖动对象 - 用户在时间
t2
释放位置(x2, y2)
处的对象 - 使用点
(x1, y1)
和(x2, y2)
的基本三角法可以为您提供运动方向,以及两个点之间的距离 - 使用
t1
和t2
之间的距离和时间差来计算运动的初始速度 - 定义一个常数来定义速度随时间的下降,我们称之为减速
- 对于每个刻度:
- 根据以前的速度和减速度计算当前速度
- 使用当前速度和方向来计算对象的新位置
- 当当前速度达到零时结束
这里有一个非常基本的JavaScript实现,它只使用方向向量,而不是分别计算方向和速度:
class Flick {
static tick = 10;
static deceleration = .875;
constructor(element) {
this.element = element;
this.element.addEventListener('dragstart', (e) => this.start(e));
this.element.addEventListener('dragend', (e) => this.end(e));
this.interval = null;
}
start(e) {
const {screenX, screenY} = e;
this.p1 = [screenX, screenY];
this.t1 = Date.now();
this.clear();
}
end(e) {
const {screenX, screenY} = e;
this.p2 = [screenX, screenY];
this.t2 = Date.now();
this.animate();
}
animate() {
const [x1, y1] = this.p1
const [x2, y2] = this.p2
const [dx, dy] = [x2 - x1, y2 - y1];
const t = this.t2 - this.t1
this.move(dx, dy);
this.vector = [dx * Flick.tick / t, dy * Flick.tick / t];
this.interval = setInterval(() => {
const [dx, dy] = this.vector;
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {
this.clear();
} else {
this.move(dx, dy);
this.vector = [dx * Flick.deceleration, dy * Flick.deceleration];
}
}, Flick.tick);
}
move(dx, dy) {
const {x, y} = this.element.getBoundingClientRect();
this.element.style.left = Math.round(x + dx) + 'px';
this.element.style.top = Math.round(y + dy) + 'px';
}
clear() {
this.interval && clearInterval(this.interval);
}
}
new Flick(document.getElementById('object'));
#object {
width: 50px;
height: 50px;
background-color: teal;
position: absolute;
}
<div id="object" draggable="true"></div>