我们拿下图中的沿着线段轨迹移动的原点来举例,怎么来实现这个动画!

1)定义路径集合Path,里面规定关键坐标点如startPoint和endPoint,设置从startPoint移动到endPoint的时间duration。

如下json对象,我们有6段路径,分别进行了定义。我们将下面这个列表集合命名为path。

 1 [
2 {
3 "startPoint": {
4 "x": 252.86249999999995,
5 "y": 191.39166666666665
6 },
7 "endPoint": {
8 "x": 252.86249999999995,
9 "y": 169.66666666666666
10 },
11 "duration": 3000
12 },
13 {
14 "startPoint": {
15 "x": 251.62499999999994,
16 "y": 169.66666666666666
17 },
18 "endPoint": {
19 "x": 393.52499999999986,
20 "y": 226.2833333333333
21 },
22 "duration": 15000
23 },
24 {
25 "startPoint": {
26 "x": 393.52499999999986,
27 "y": 226.2833333333333
28 },
29 "endPoint": {
30 "x": 393.52499999999986,
31 "y": 427.075
32 },
33 "duration": 15000
34 },
35 {
36 "startPoint": {
37 "x": 385.6874999999999,
38 "y": 420.4916666666667
39 },
40 "endPoint": {
41 "x": 385.6874999999999,
42 "y": 407.2916666666667
43 },
44 "duration": 3000
45 },
46 {
47 "startPoint": {
48 "x": 385.6874999999999,
49 "y": 407.2916666666667
50 },
51 "endPoint": {
52 "x": 125.8125,
53 "y": 421.94166666666666
54 },
55 "duration": 15000
56 },
57 {
58 "startPoint": {
59 "x": 126.6375,
60 "y": 421.94166666666666
61 },
62 "endPoint": {
63 "x": 126.6375,
64 "y": 434.31666666666666
65 },
66 "duration": 3000
67 }
68 ]

2)每次事件循环执行代码都会计算一个坐标值

怎么计算新坐标?具体就是如下代码:

this.curTime += this.timeFreshTime;
let currentX = Easing.Linear(this.curTime, this.movePath.startPoint.x, this.movePath.endPoint.x - this.movePath.startPoint.x, this.movePath.duration);
let currentY = Easing.Linear(this.curTime, this.movePath.startPoint.y, this.movePath.endPoint.y - this.movePath.startPoint.y, this.movePath.duration);

利用当前时间,起点,终点。我们借助时间曲线easing库,里面的计算专为动画设计,还有我之前介绍过一个运算库《Tween算法及缓动效果》都是一样的。

代码参考如下:

  1 export class Easing {
2 // t: current time(当前时间),
3 // b: beginning value(初始值),
4 // c: chang in value (变化量),
5 // d: duration(持续时间)
6 static Linear = function (t, b, c, d) { return c * t / d + b; };
7 static Quad = {
8 easeIn: function (t, b, c, d) {
9 return c * (t /= d) * t + b;
10 },
11 easeOut: function (t, b, c, d) {
12 return -c * (t /= d) * (t - 2) + b;
13 },
14 easeInOut: function (t, b, c, d) {
15 if ((t /= d / 2) < 1) return c / 2 * t * t + b;
16 return -c / 2 * ((--t) * (t - 2) - 1) + b;
17 }
18 };
19 static Cubic = {
20 easeIn: function (t, b, c, d) {
21 return c * (t /= d) * t * t + b;
22 },
23 easeOut: function (t, b, c, d) {
24 return c * ((t = t / d - 1) * t * t + 1) + b;
25 },
26 easeInOut: function (t, b, c, d) {
27 if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
28 return c / 2 * ((t -= 2) * t * t + 2) + b;
29 }
30 };
31 static Quart = {
32 easeIn: function (t, b, c, d) {
33 return c * (t /= d) * t * t * t + b;
34 },
35 easeOut: function (t, b, c, d) {
36 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
37 },
38 easeInOut: function (t, b, c, d) {
39 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
40 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
41 }
42 };
43 static Quint = {
44 easeIn: function (t, b, c, d) {
45 return c * (t /= d) * t * t * t * t + b;
46 },
47 easeOut: function (t, b, c, d) {
48 return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
49 },
50 easeInOut: function (t, b, c, d) {
51 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
52 return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
53 }
54 };
55 static Sine = {
56 easeIn: function (t, b, c, d) {
57 return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
58 },
59 easeOut: function (t, b, c, d) {
60 return c * Math.sin(t / d * (Math.PI / 2)) + b;
61 },
62 easeInOut: function (t, b, c, d) {
63 return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
64 }
65 };
66 static Expo = {
67 easeIn: function (t, b, c, d) {
68 return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
69 },
70 easeOut: function (t, b, c, d) {
71 return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
72 },
73 easeInOut: function (t, b, c, d) {
74 if (t == 0) return b;
75 if (t == d) return b + c;
76 if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
77 return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
78 }
79 };
80 static Circ = {
81 easeIn: function (t, b, c, d) {
82 return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
83 },
84 easeOut: function (t, b, c, d) {
85 return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
86 },
87 easeInOut: function (t, b, c, d) {
88 if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
89 return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
90 }
91 };
92 static Elastic = {
93 easeIn: function (t, b, c, d, a, p) {
94 var s;
95 if (t == 0) return b;
96 if ((t /= d) == 1) return b + c;
97 if (typeof p == "undefined") p = d * .3;
98 if (!a || a < Math.abs(c)) {
99 s = p / 4;
100 a = c;
101 } else {
102 s = p / (2 * Math.PI) * Math.asin(c / a);
103 }
104 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
105 },
106 easeOut: function (t, b, c, d, a, p) {
107 var s;
108 if (t == 0) return b;
109 if ((t /= d) == 1) return b + c;
110 if (typeof p == "undefined") p = d * .3;
111 if (!a || a < Math.abs(c)) {
112 a = c;
113 s = p / 4;
114 } else {
115 s = p / (2 * Math.PI) * Math.asin(c / a);
116 }
117 return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
118 },
119 easeInOut: function (t, b, c, d, a, p) {
120 var s;
121 if (t == 0) return b;
122 if ((t /= d / 2) == 2) return b + c;
123 if (typeof p == "undefined") p = d * (.3 * 1.5);
124 if (!a || a < Math.abs(c)) {
125 a = c;
126 s = p / 4;
127 } else {
128 s = p / (2 * Math.PI) * Math.asin(c / a);
129 }
130 if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
131 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
132 }
133 };
134 static Back = {
135 easeIn: function (t, b, c, d, s) {
136 if (typeof s == "undefined") s = 1.70158;
137 return c * (t /= d) * t * ((s + 1) * t - s) + b;
138 },
139 easeOut: function (t, b, c, d, s) {
140 if (typeof s == "undefined") s = 1.70158;
141 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
142 },
143 easeInOut: function (t, b, c, d, s) {
144 if (typeof s == "undefined") s = 1.70158;
145 if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
146 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
147 }
148 };
149 static Bounce = {
150 easeIn: function (t, b, c, d) {
151 return c - Easing.Bounce.easeOut(d - t, 0, c, d) + b;
152 },
153 easeOut: function (t, b, c, d) {
154 if ((t /= d) < (1 / 2.75)) {
155 return c * (7.5625 * t * t) + b;
156 } else if (t < (2 / 2.75)) {
157 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
158 } else if (t < (2.5 / 2.75)) {
159 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
160 } else {
161 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
162 }
163 },
164 easeInOut: function (t, b, c, d) {
165 if (t < d / 2) {
166 return Easing.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
167 } else {
168 return Easing.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
169 }
170 }
171 }
172 }

Easing

3)当前坐标点已计算更新,此时在新位置处绘制白色点,我们的事件循序间隔设置的50ms,所有能够产生平滑移动的效果。

4)实际需要几个移动的白点,那就需要定义几个path。如上gif图中我们有两个path,这两个path初始化的时间是错开的,所有才产生非同步移动的效果。

5)当一个path走完,再让其从头走(path的第一个startPoint endPoint),这样不断地循环下去。

canvas绘制动画的技巧的更多相关文章

  1. Android中使用SurfaceView和Canvas来绘制动画

    事实上每一个View中都有Canvas能够用来绘制动画.仅仅须要在这个View中重载onDraw()方法就能够,可是SurfaceView类是一个专门用来制动动画的类. Canvas(中文叫做&quo ...

  2. canvas绘制简易动画

    在canvas画布中制作动画相对来说很简单,实际上就是不断变化的坐标.擦除.重绘的过程 1.使用setInterval方法设置动画的间隔时间. setInterval(code,millisec) s ...

  3. canvas 绘制双线技巧

    楔子 最近一个项目,需要绘制双线的效果,双线效果表示的是轨道(类似铁轨之类的),如下图所示: 负责这块功能开发的小伙,姑且称之为L吧,最开始是通过数学计算的方式来实现这种双线,也就是在原来的路径的基础 ...

  4. 第165天:canvas绘制圆环旋转动画

    canvas绘制圆环旋转动画——面向对象版 1.HTML 注意引入Konva.js库 <!DOCTYPE html> <html lang="en"> &l ...

  5. h5学习-canvas绘制矩形、圆形、文字、动画

    绘制矩形<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  6. canvas绘制折线路径动画

    最近有读者加我微信咨询这个问题: 其中的效果是一个折线路径动画效果,如下图所示: 要实现以上路径动画,一般可以使用svg的动画功能.或者使用canvas绘制,结合路径数学计算来实现. 如果用canva ...

  7. canvas小球动画

    绘制小球 我们将会画一个小球用于动画学习,所以首先在画布上画一个球.下面的代码帮助我们建立画布. <canvas id="></canvas> 跟平常一样,我们需要先 ...

  8. 使用Canvas绘制背景图

    原文  http://www.imququ.com/post/use-canvas-as-background-image.html 最近iCloud Web的Beta版换了UI,整体风格变得和iOS ...

  9. 使用 HTML5 Canvas 绘制出惊艳的水滴效果

    HTML5 在不久前正式成为推荐标准,标志着全新的 Web 时代已经来临.在众多 HTML5 特性中,Canvas 元素用于在网页上绘制图形,该元素标签强大之处在于可以直接在 HTML 上进行图形操作 ...

随机推荐

  1. 29.Map,可变参数

    1.Map集合 1.1Map集合概述和特点[理解] 单列集合一次存一个元素 双列集合一次存两个元素 键:不能重复的        值:可以重复的 Map集合概述 interface Map<K, ...

  2. [bug] CDH 安装 哈希验证失败

    分析 验证 parcel 文件的哈希值 和 sha 文件不一致:文件损坏,重新下载 和 sha 官网一致:配置httpd文件 参考 哈希值和官网不一致 https://blog.csdn.net/lv ...

  3. make clean 清除之前编译的可执行文件及配置文件。 make distclean 清除所有生成的文件。

    https://blog.csdn.net/bb807777/article/details/108302105 make clean 清除之前编译的可执行文件及配置文件.make distclean ...

  4. (KVM连载) 8.2.3 KVM CPU性能测试方法

    (KVM连载) 8.2.3 KVM CPU性能测试方法 01/08/2013MASTER  2 COMMENTS 8.2.3 性能测试方法 本节的CPU性能测试选取了SPEC CPU2006.内核编译 ...

  5. rsync同步遇到的报错和解决办法

    rsync同步遇到的报错和解决办法   科技小能手 2017-11-12 18:27:00 浏览1125 配置 code 同步 open stream file read   在同步的客户端操作: [ ...

  6. 004.kubernets对于pod的简单管理

    一 pod简介 1.1 介绍 Pod是K8s集群中所有业务类型的基础 Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的. Pod的设计理念是支持多个容器在一个Pod中共享网络地 ...

  7. shell基础之变量及表达式

    本节内容 1. shell变量简介 2. 定义变量 3. 使用变量 4. 修改变量的值 5. 单引号和双引号的区别 6. 将命令的结果赋值给变量 7. 删除变量 8. 变量类型 9. 特殊变量列表 1 ...

  8. STM32 KEIL 下的 printf 函数

    1 //加入以下代码,支持printf函数,而不需要选择use MicroLIB 2 #if 1 3 #pragma import(__use_no_semihosting) 4 //标准库需要的支持 ...

  9. 逗号字符的使用、字符数组与字符串数组、sizeof与strlen

    (1)连接两个表达式为一个表达式 for(ux=0,uxt=1;uxt<444;ux++,uxt++) 允许通过编译:他可以给FOR循环更多的初始化值: (2)一般定义的话要区别只有 字符数组 ...

  10. Java反射机制详情

    1.运行环境 JDK8+lntellij IDEA 2018.3 2.反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个 ...