Fork me on GitHub

使用贝塞尔曲线实现元素沿曲线运动

业务场景

最近业务中遇到了一个点赞需求,就很常见的那种直播点赞,设计上要求点赞气泡随机沿着弧线运动路径向上飞,简单点可以把关键帧动画硬编码,但是我感觉那么做不是很完美,就想到了用贝塞尔曲线来实现这个功能

贝塞尔算法

贝塞尔曲线知识就不科普了,我也不咋懂,一般也就用二阶或者三阶贝塞尔,直接上代码,也可以使用现成库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const bezier = {
/**
* @desc 二阶贝塞尔
* @param {number} t 当前百分比(0~1)
* @param {Array} p1 起点坐标
* @param {Array} cp 控制点
* @param {Array} p2 终点坐标
*/
quad(t, p1, cp, p2) {
const [x1, y1] = p1;
const [cx, cy] = cp;
const [x2, y2] = p2;
const x = Math.pow(1 - t, 2) * x1 + 2 * (1 - t) * t * cx + Math.pow(t, 2) * x2;
const y = Math.pow(1 - t, 2) * y1 + 2 * (1 - t) * t * cy + Math.pow(t, 2) * y2;
return [x, y];
},
/**
* @desc 三阶贝塞尔
* @param {number} t 当前百分比(0~1)
* @param {Array} p1 起点坐标
* @param {Array} cp1 控制点1
* @param {Array} cp2 控制点2
* @param {Array} p2 终点坐标
*/
cubic(t, p1, cp1, cp2, p2) {
const [x1, y1] = p1;
const [x2, y2] = p2;
const [cx1, cy1] = cp1;
const [cx2, cy2] = cp2;
const x = Math.pow(1 - t, 3) * x1 + 3 * Math.pow(1 - t, 2) * t * cx1 + 3 * (1 - t) * Math.pow(t, 2) * cx2 + Math.pow(t, 3) * x2;
const y = Math.pow(1 - t, 3) * y1 + 3 * Math.pow(1 - t, 2) * t * cy1 + 3 * (1 - t) * Math.pow(t, 2) * cy2 + Math.pow(t, 3) * y2;
return [x, y];
},
};

先写个 demo 测试一下算法

用 canvas 测试一下上边的算法是否可用
归根揭底,上边贝塞尔函数中的参数 t 是代表了百分比或者理解为进度(0 ~ 1),所以曲线精度完全取决于每次的 t 值间隔

玩点炫的(情人节限定版)

这里为了方便我使用了 web animation api,贝塞尔曲线只是个算法,如果你愿意,你完全可以使用任意你想要的方式

以上 demo 都可以在 stackblitz 上实时编辑