跨屏幕抛出元素的算法

问题描述

我有一个应用程序,我希望用户能够在屏幕上投掷/轻弹一个对象。本质上,他们会快速地将元素拖过屏幕然后松开,然后它会继续以相同的速度向他们拖入的方向移动,然后减速直到停止。

任何语言或伪代码的答案将不胜感激。或者,如果您可以指出此算法的名称,那也会有所帮助。 谢谢

解决方法

我会找到鼠标移动的速度并将对象的速度设置为鼠标的速度。 物体速度=鼠标速度 然后每刻降低该速度,直到达到 0。

如果你想让它更逼真,我会看这里:https://physics.stackexchange.com/questions/391318/how-to-calculate-a-change-in-velocity-as-a-result-of-friction

,

这是我的尝试:

  1. 用户在 (x1,y1) 时间开始在位置 t1 拖动对象
  2. 用户在 (x2,y2) 时间释放位置 t2 的对象
  3. 使用点 (x1,y1)(x2,y2) 的基本三角学为您提供移动方向,以及两个点之间的距离
  4. 使用t1t2之间的距离时间差来计算运动的初始速度 .
  5. 定义一个常数来定义速度随时间的减少,我们称之为减速
  6. 对于每个刻度:
    1. 根据先前速度减速度计算当前速度
    2. 使用当前速度方向来计算对象的新位置。
  7. 当前速度达到零时结束。

这是一个非常基本的 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>