js 动画补间 Tween
1 /* RunningList (触发过程中可以安全的删除自己)
2 如果触发过程中删除(回调函数中删除正在遍历的数组), 不仅 len 没有变(遍历前定义的len没有变, 真实的len随之减少), 而且还会漏掉一个key;
3
4 */
5 class RunningList{
6
7 static getProxy(runName){
8
9 return new Proxy(new RunningList(runName), {
10
11 get(tar, key){
12
13 },
14
15 set(tar, key, val){
16
17 }
18
19 });
20
21 }
22
23 constructor(runName = 'update'){
24 this._running = false;
25 this._list = [];
26 this._delList = [];
27 this._runName = runName;
28
29 }
30
31 get length(){
32 return this._list.length;
33 }
34
35 push(v){
36 this._list.push(v);
37
38 }
39
40 splice(v){
41 if(this._running === true) this._delList.push(v);
42
43 else{
44 const i = this._list.indexOf(v);
45 if(i !== -1) this._list.splice(i, 1);
46 }
47
48 }
49
50 update(){
51 var k, len = this._list.length;
52
53 this._running = true;
54 for(k = 0; k < len; k++) this._list[k][this._runName]();
55 this._running = false;
56
57 len = this._delList.length;
58 for(k = 0; k < len; k++) this.splice(this._delList[k]);
59 this._delList.length = 0;
60
61 }
62
63 }
64
65
66
67
68 /* TweenValue (从 原点 以规定的时间到达 终点)
69
70 parameter: origin, end, time, onUpdate, onEnd;
71
72 attribute:
73 origin: Object; //原点(起点)
74 end: Object; //终点
75 time: Number; //origin 到 end 花费的时间
76 onUpdate: Function; //更新回调; 一个回调参数 origin; 默认null;
77 onEnd: Function; //结束回调; 没有回调参数; 默认null; (如果返回的是true将不从队列删除, 你可以在onEnd中更新.end不间断的继续补间)
78
79 method:
80 reset(origin, end: Object): undefined; //更换 .origin, .end; 它会清除其它对象的缓存属性
81 reverse(): undefined; //this.end 复制 this.origin 的原始值
82 update(): undefined; //Tween 通过此方法统一更新 TweenValue
83
84 demo:
85 //init Tween:
86 const tween = new Tween(),
87 animate = function (){
88 requestAnimationFrame(animate);
89 tween.update();
90 }
91
92 //init TweenValue:
93 const v1 = new Tween.Value({x:0, y:0}, {x:5, y:10}, 1000, v => console.log(v));
94
95 animate();
96 tween.start(v1);
97
98 */
99 class TweenValue{
100
101 constructor(origin = {}, end = {}, time = 500, onUpdate = null, onEnd = null, onStart = null){
102 this.origin = origin;
103 this.end = end;
104 this.time = time;
105
106 this.onUpdate = onUpdate;
107 this.onEnd = onEnd;
108 this.onStart = onStart;
109
110 //以下属性不能直接设置
111 this._r = null;
112 this._t = 0;
113 this._v = Object.create(null);
114
115 }
116
117 _start(){
118 var v = "";
119 for(v in this.origin) this._v[v] = this.origin[v];
120
121 this._t = Date.now();
122 //this.update();
123
124 }
125
126 reset(origin, end){
127 this.origin = origin;
128 this.end = end;
129 this._v = Object.create(null);
130
131 }
132
133 reverse(){
134 var n = "";
135 for(n in this.origin) this.end[n] = this._v[n];
136
137 }
138
139 update(){
140 if(this["_r"] !== null){
141
142 var ted = Date["now"]() - this["_t"];
143
144 if(ted >= this["time"]){
145
146 for(ted in this["origin"]) this["origin"][ted] = this["end"][ted];
147 if(this["onUpdate"] !== null) this["onUpdate"](this["origin"]);
148
149 if(this["onEnd"] !== null){
150
151 if(this["onEnd"]() !== true){
152 if(this["_r"] !== null) this["_r"]["stop"](this);
153 }
154
155 else this["_start"]();
156
157 }
158
159 else this["_r"]["stop"](this);
160
161 }
162
163 else{
164 let n = "";
165 ted = ted / this["time"];
166 for(n in this["origin"]) this["origin"][n] = ted * (this["end"][n] - this["_v"][n]) + this["_v"][n];
167 if(this["onUpdate"] !== null) this["onUpdate"](this["origin"]);
168
169 }
170
171 }
172
173 }
174
175 }
176
177 Object.defineProperties(TweenValue.prototype, {
178
179 isTweenValue: {
180 configurable: false,
181 enumerable: false,
182 writable: false,
183 value: true,
184 }
185
186 });
187
188
189
190
191 /* TweenAlone (相对于 TweenValue 此类可以独立补间, 不需要 Tween)
192
193 demo:
194 const v1 = new TweenAlone({x:0, y:0}, {x:5, y:10}, 1000, v => console.log(v)),
195 animate = function (){
196 requestAnimationFrame(animate);
197 v1.update();
198 }
199
200 animate();
201 v1.start();
202
203 */
204 class TweenAlone extends TweenValue{
205
206 constructor(origin, end, time, onUpdate, onEnd, onStart){
207 super(origin, end, time, onUpdate, onEnd, onStart);
208
209 }
210
211 start(){
212 if(this.onStart !== null) this.onStart();
213 this._r = this;
214 this._start();
215
216 }
217
218 stop(){
219 this._r = null;
220
221 }
222
223 }
224
225
226
227
228
229 /* Tween 动画补间 (TweenValue 的root, 可以管理多个TweenValue)
230
231 parameter:
232 attribute:
233 method:
234 start(value: TweenValue): undefined;
235 stop(value: TweenValue): undefined;
236
237 static:
238 Value: TweenValue;
239
240 demo:
241 //init Tween:
242 const tween = new Tween(),
243 animate = function (){
244 requestAnimationFrame(animate);
245 tween.update();
246 }
247
248 //init TweenValue:
249 const v2 = new Tween.Value({x:0, y:0}, {x:5, y:10}, 1000, v => console.log(v), v => {
250 v2.reverse(); //v2.end 复制起始值
251 return true; //返回true表示不删除队列, 需要继续补间
252 });
253
254 animate();
255 tween.start(v2);
256
257 */
258 class Tween extends RunningList{
259
260 static Value = TweenValue;
261
262 constructor(){
263 super();
264
265 }
266
267 start(value){
268 if(value.onStart !== null) value.onStart();
269 if(value._r === null) this.push(value);
270 value._r = this;
271 value._start(this);
272
273 }
274
275 stop(value){
276 if(value._r !== null) this.splice(value);
277 value._r = null;
278
279 }
280
281 }
282
283
284
285
286 /* TweenTargetChange 朝着轴插值(有效的跟踪动态目标)
287 parameter:
288 v1 = {x: 0},
289 v2 = {x: 100},
290 distance = 1, //每次移动的距离
291 onUpdate = null, //
292 onEnd = null
293
294 attribute:
295 v1: Object; //起点
296 v2: Object; //终点
297 onUpdate: Function; //
298 onEnd: Function; //
299
300 method:
301 update(): undefined; //一般在动画循环里执行此方法
302 updateAxis(): undefined; //更新v1至v2的方向轴 (初始化时构造器自动调用一次)
303 setDistance(distance: Number): undefined; //设置每次移动的距离 (初始化时构造器自动调用一次)
304
305 demo:
306 const ttc = new TweenTargetChange({x:0, y:0}, {x:100, y:100}, 10),
307
308 //计时器模拟动画循环函数, 每秒执行一次.update()
309 timer = new Timer(() => {
310 ttc.update();
311 console.log('update: ', ttc.v1);
312
313 }, 1000, Infinity);
314
315 ttc.onEnd = v => {
316 timer.stop();
317 console.log('end: ', v);
318 }
319
320 timer.start();
321 console.log(ttc);
322
323 */
324 class TweenTargetChange{
325
326 #distance = 1;
327 #distancePow2 = 1;
328 #axis = {};
329
330 constructor(v1 = {x: 0}, v2 = {x: 100}, distance, onUpdate = null, onEnd = null){
331 this.v1 = v1;
332 this.v2 = v2;
333 this.onUpdate = onUpdate;
334 this.onEnd = onEnd;
335
336 this.setDistance(distance);
337 this.updateAxis();
338 }
339
340 setDistance(v = 1){
341 this.#distance = v;
342 this.#distancePow2 = Math.pow(v, 2);
343
344 }
345
346 updateAxis(){ //更新轴
347 var n, v, len = 0;
348
349 for(n in this.v1){
350 v = this.v2[n] - this.v1[n];
351 len += v * v;
352 this.#axis[n] = v;
353
354 }
355
356 len = Math.sqrt(len);
357
358 if(len !== 0){
359
360 for(n in this.v1) this.#axis[n] *= 1 / len;
361
362 }
363
364 }
365
366 update(){
367 var n, len = 0;
368
369 for(n in this.v1) len += Math.pow(this.v1[n] - this.v2[n], 2);
370
371 if(len > this.#distancePow2){
372
373 for(n in this.v1) this.v1[n] += this.#axis[n] * this.#distance;
374 if(this.onUpdate !== null) this.onUpdate(this.v1);
375
376 }
377
378 else{
379 for(n in this.v1) this.v1[n] = this.v2[n];
380 if(this.onEnd !== null) this.onEnd(this.v1);
381
382 }
383
384 }
385
386 }
完整代码
js 动画补间 Tween的更多相关文章
- Android动画-补间(Tween)动画
Android动画的两种方式,其中帧动画上篇文章已经讲了,这次主要讲解的就是补间动画,补间动画就是动画业务场景中常用的旋转,平移,缩放,和渐变效果,帧动画是通过轮播动画实现动画效果,补间动画通过在两个 ...
- android 帧动画,补间动画,属性动画的简单总结
帧动画——FrameAnimation 将一系列图片有序播放,形成动画的效果.其本质是一个Drawable,是一系列图片的集合,本身可以当做一个图片一样使用 在Drawable文件夹下,创建ani ...
- 属性动画 补间动画 帧动画 基本使用案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Android笔记(六十四) android中的动画——补间动画(tweened animation)
补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...
- Android 动画 属性动画 视图动画 补间动画 帧动画 详解 使用
Android动画 Property Animation res/animator/filename.xml In Java: R.animator.filename In XML: @[packag ...
- WebGL three.js学习笔记 加载外部模型以及Tween.js动画
WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...
- Android基础笔记(十)- 帧动画、补间动画具体解释、对话框
帧动画 补间动画Tween Animation 对话框以及面试中的注意点 帧动画 帧动画非常easy,我们首先看一下Google官方解释This is a traditional animation ...
- 高速上手Unity中最好的补间动画插件DFTween
出处:http://blog.csdn.net/u010019717 author:孙广东 时间:2015.3.17 23:00 DFTween 是一个在 Unity 游戏引擎中高 ...
- Android 深入ViewPager补间动画,实现类京东商城首页广告Banner切换效果
如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 某天看到京东商城首页的滑动广告的Banner,在流动切换的时候有立体的动画效果,感觉很有意思,然后研究了下 ...
随机推荐
- 纯JS实现KeyboardNav(学习笔记)二
纯JS实现KeyboardNav(学习笔记)二 这篇博客只是自己的学习笔记,供日后复习所用,没有经过精心排版,也没有按逻辑编写 这篇主要是添加css,优化js编写逻辑和代码排版 GitHub项目源码 ...
- 使用element UI el-upload组件实现视频文件上传及上传进度显示方法总结
实现效果: 上传中: 上传完成: 代码: <el-form-item label="视频上传" prop="Video"> <!-- acti ...
- MySQL---drop, delete, truncate的区别
drop, delete, truncate的区别 删除内容 drop直接删除整个表, 包含表结构和数据; truncate删除表中数据, 表结构及其列, 约束, 索引等不变, 再插入时自增id又从1 ...
- 巧用 background-clip 实现超强的文字动效
最近,有同学询问,如何使用 CSS 实现如下效果: 看起来是个很有意思的动效. 仔细思考一下,要想实现这类效果,其实用到的核心属性只有一个 -- background-clip: text. 有意思的 ...
- 2021.12.16 eleveni的刷题记录
2021.12.16 eleveni的刷题记录 1. 数论 https://www.luogu.com.cn/problem/P2532 1.1卡特兰数 https://www.luogu.com.c ...
- 手把手带你入门ECharts
1.什么是ECharts ECharts,缩写来自Enterprise Charts,商业级数据图表,是来自百度商业前端数据可视化团队EFE的一个开源的纯Javascript的图表库,可以流畅的运行在 ...
- zookeeper篇-zk的选举机制
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 说说zk的选举机制 基础概念 zxid=事务id=一个时间戳,代表当前事 ...
- Python求解线性规划——PuLP使用教程
简洁是智慧的灵魂,冗长是肤浅的藻饰.--莎士比亚<哈姆雷特> 1 PuLP 库的安装 如果您使用的是 Anaconda[1] 的话(事实上我也更推荐这样做),需要先激活你想要安装的虚拟环境 ...
- Nessus简单介绍与安装
1.Nessus简单介绍与安装 1.Nessus简介 Nessus号称是世界上最流行的漏洞扫描程序,全世界有超过75000个组织在使用它.该工具提供完整的电脑漏洞扫描服务,并随时更新其漏洞数据库.Ne ...
- SmartIDE v0.1.16 已经发布 - 支持阿里&蚂蚁开源的国产 IDE OpenSumi
SmartIDE v0.1.16 (Build 3137) 已经在2022年4月19日发布到稳定版通道,我们在这个版本中增加了阿里和蚂蚁发布的国产IDE OpenSumi的支持,以及其他一些改进.Sm ...