canvas:摸得着的前端动画

lxf2023-04-14 08:55:01

你在凝望深渊的时候,深渊也在凝望你。——Who(你猜

这也是交互吗?

什么叫交互

看电影是交互吗?不是,你的行为影响不了画面(你把屏幕砸坏的行为除外

玩游戏是交互吗?是的,你能控制游戏角色的行为。

你的行为,比如移动鼠标、敲下键盘、在摄像头前摇摇头、喊一声Siri,通过输入设备能对画面产生变化的,就叫交互。

事件与监听

你的特定行为能被电脑感知,是因为触发(emit)了特定事件,同时电脑有监听(on)这一事件,并执行针对这一事件发生后的对应操作(callback)。

你移动鼠标,画面就会有个鼠标跟着你的行为移动;

你点击图标,画面上的图标就会是选中状态;

你拿着鼠标抠脚,画面根本不会有什么反应,因为它没有监听你用鼠标抠脚这种事件。

鼠标事件获取交互数据

我们拿鼠标事件举例,简单讲讲鼠标与屏幕的交互。

鼠标事件的目的大多数是根据事件类型(按下、松开、移动)获取所在的位置(x,y)。

mousedown
mouseup
mouseenter
mouseleave
mouseout
mouseover
...

试下在任意一个网页的控制台输入并运行window.onmousedown = console.log,再点击网页的任意位置,就会输出以下信息:

我截取了部分即便是非程序员也多少能看得懂的属性

altKey: true // 是否同时按下alt键
button: 0 // 左键、滚轮键or右键
ctrlKey: false // 是否同时按下ctrl键
shiftKey: false // 是否同时按下shift键
x: 852
y: 180

  1. x、y就是鼠标位置,用于判断点是否在形状之内,比如有没有选中图标

  2. button就是按键类型,玩CS的右键瞄准、左键攻击

  3. 点鼠标的时候同时点击ctrl能选中多个文件

除了鼠标事件以外,还有其他输入设备产生交互的事件,比如键盘(keydown、keyup)、触控屏(touchstart、touchend),这些事件存在的意义就是让我们了解用户交互行为的详细信息,然后写一些对应的操作,比如动画。

交互对数据的影响

如果数据也符合牛顿第一定律,那么数据一开始是静止的,它发生变化一定是受到了外力的作用,这个外力就是交互。

canvas:摸得着的前端动画

交互会触发事件,事件记录当时的交互数据,交互数据和其他数据之间会有运算。

  1. 移动鼠标,鼠标的位置(x,y)必然变化,属于交互数据的变化

  2. 画面有一个按钮,属于其他数据

  3. 鼠标来到按钮上,两者之间的运算得出一个结果:isIntersected: true,这就是交互对数据的影响

你喜欢怎么表达这个运算结果都可以,温柔点,你可以让按钮变色;粗暴点,你可以让它爆炸。

canvas:摸得着的前端动画

数据的变化引起的动画

画面的本质是数据,数据发生变化,画面随之变化。

我们遵循以下规则:

  1. 交互->数据,通过交互改变数据

  2. 数据->绘制,根据当前的数据绘制画面

也就是说,交互不直接调用绘制函数,第1条是本篇文章的核心,第2条是上一篇的核心,数据静止就是静态画面,数据变化就变成了动画。

实践

上一篇,我们写了一个简单的二维运动,我们在这个二维运动的基础上加入鼠标交互:圆心在鼠标方圆五百里内(换算一下就是100px,当然这是我瞎扯的)的粒子变大

获取交互数据

这里的交互数据是鼠标位置,设一个全局变量mouse

const mouse = {
    x: 0;
    y: 0;
}

监听鼠标移动事件,移动时更新mouse

window.addEventListener('mousemove', (e) => {
  mouse.x = e.x;
  mouse.y = e.y;
});

通过交互更新数据

沿用上一篇文章的结构,粒子类有个update函数,在这里更新交互带来的数据影响。

在此增加minRmaxR作为粒子变大变小的极值。

class Particle {
    ...
  update() {
      ...
      // 勾股定理,两点距离<100,粒子变大,否则变小
    if (Math.sqrt((mouse.x - this.x) ** 2 + (mouse.y - this.y) ** 2) <= 100) {
      if (this.r < this.maxR) {
        this.r += 1;
      }
    } else if (this.r > this.minR) {
      this.r -= 1;
    }

    this.x += this.dx;
    this.y += this.dy;
    this.draw();
  }
}

效果如下:

canvas:摸得着的前端动画

如果你觉得这个不是很有趣,不妨看看下面这个效果:

  1. 鼠标松开的时候做抛体运动

  2. 鼠标按下的时候做向心加速运动

canvas:摸得着的前端动画

可以提前思考一下这个效果怎么实现,如无意外,后两篇就是介绍向量和力的可视化了。

つづく

本文简单介绍并实现了交互事件在canvas中的运用,喜欢的朋友可以点个赞,也欢迎大家关注dkplus公众号,没东西写的时候说不定就开始画画了。