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

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. git取消更改 恢复版本命令

      #删除远程的xxx分支 git push origin :xxx #取消对文件的修改.还原到最近的版本,废弃本地做的修改. git checkout -- <file>   #取消已经 ...

  2. AOP随笔

    AOP: Aspect-Oriented Programming 面向切面编程. 首先明确一个点:AOP是一个概念.那么对于一个概念,其实现方式多种多样,分为静态AOP.动态AOP,而对于动态AOP的 ...

  3. 前端的MySQL基础

    前端MySQL 一.引言 MySQL是一个关系型数据库管理系统,在Web应用方面,MySQL是最好的应用之一.其主要的他点是体积小.速度块.总体成本低.源码开放 二.MySQL的构成 在我们开始学习M ...

  4. [Qt] 项处理组件

                             项(Item):一个项存储了文字.文字的格式.自定义数据等. 1.项视图(Item View) 针对一个数据模型,可能有不同的展示需求,如文件夹中图片 ...

  5. 搭建LAMP环境部署GLPI资源管理系统

    搭建LAMP环境部署GLPI资源管理系统 一.关闭防火墙和Selinux [root@localhost ~]# systemctl disable --now firewalld [root@loc ...

  6. linux 详解useradd 命令基本用法

    linux 详解useradd 命令基本用法 时间:2019-03-24 本文章向大家介绍linux 详解useradd 命令基本用法,主要包括linux 详解useradd 命令基本用法使用实例.应 ...

  7. 分布式存储ceph---部署ceph(2)

    一.部署准备 准备5台机器(linux系统为centos7.6版本),当然也可以至少3台机器并充当部署节点和客户端,可以与ceph节点共用: 1台部署节点(配一块硬盘,运行ceph-depoly) 3 ...

  8. 荷小鱼 x mPaaS | 借助 H5 容器改善 App 白屏、浏览器兼容等问题

      随着5G.大数据.人工智能技术的应用,各类传统行业纷纷大力推进数字化转型升级. 而受疫情的影响,教育行业也在大幅加速线上化转型进程,各类在线教育应用也在借助各种力量拓张自己的移动端市场领域. 「荷 ...

  9. 微信小程序开发(后端Java)

    微信使用的开发语言和文件很「特殊」. 小程序所使用的程序文件类型大致分为以下几种: ①WXML(WeiXin Mark Language,微信标记语言) ②WXSS(WeiXin Style Shee ...

  10. 重新整理 .net core 实践篇—————配置文件之环境配置[九]

    前言 在当今在互联网微服务比较适用的情况下,docker 可以说一个利器.每次我们打包docker的时候都是适用docker 的配置文件,那么配置文件里面会设置环境变量,这个时候需要我们的应用能够识别 ...