原生JavaScript运动功能系列(五):定时定点运动

这篇博客剖析一个问题,就是怎么实现将元素指定时间运动到目标位置?前面的博客都是在处理运动行为,没有对运动时间做任何限定,只是因为清晰的分析运动行为和实现原理,要想一个动画函数具备健全的功能,并且可以随意使用,通过参数设定动画执行时间是非常有必要的一个设计。

在前面任意一种运动函数内,实质上只有一个变量,这个变量就是运动距离(缓冲运动中添加了因数),当运动距离变大时,运动时间就会变长,动画停止条件是由坐标来决定的。当指定运动时间时,运动速度就会同时受到运动距离和运动时间的限制,动画停止条件也是由时间来控制。

定时定点运动示例代码:

 1 //css
 2 div{
 3     width:100px;
 4     height:100px;
 5     background:red;
 6     position: absolute;
 7     left: 0px;
 8     opacity: 1;
 9 }
10 #top{
11     top: 100px;
12 }
13 #bottom{
14     top: 300px;
15 }
16 //html
17 <div id="top"></div>
18 <div id="bottom"></div>
19 //js
20 var oDivArray = document.getElementsByTagName(‘div‘);
21 var timer = null;
22 var targetObj = {
23     width:400,
24     height:400,
25     opacity:50,
26     left:300,
27     top:200
28 }
29 oDivArray[0].onclick = function(){
30     startMove(this,targetObj,3000,function(){
31         startMove(oDivArray[1],targetObj,3000);
32     });
33 }
34 function getStyle(obj,attr){
35     if(window.getComputedStyle){
36         return window.getComputedStyle(obj,false)[attr];
37     }else{
38         return obj.currentStyle[attr];
39     }
40 }
41 //运动方法startMove的参数:
42 //obj:运动物体;
43 //json:目标位置,最终样式值(键值对的形式合成的目标位置对象)
44 //speed:运动时间(指定运动的时间)
45 //callback:回调函数
46 function startMove(obj,json,speed,callback){
47     //初始位置,移动距离,当前位置
48     var initialPlace = {};
49     //新的位置(每次运动的目标点)
50     var nowPlace;
51     //结束之前的定时器
52     clearInterval(obj.timer);
53     //获取当前时间戳
54     var createTime = function(){
55         return (+new Date);
56     }
57     //动画开始的时间戳
58     var startTime = createTime();
59     //初始位置对象
60     for(var attr in json){
61         if(attr == ‘opacity‘){
62             initialPlace[attr] = Math.round(parseFloat(getStyle(obj,attr))*100);
63         }else{
64             initialPlace[attr] = parseInt(getStyle(obj,attr));
65         }
66     }
67     //定时器
68     obj.timer = setInterval(function(){
69         //每次变化的时间
70         //剩余时间 = Math.max(0,运动开始的时间 + 运动执行事件 - 当前时间) -- 当剩余时间为负数时,返回0
71         var remaining = Math.max(0, startTime + speed - createTime());
72         //剩余时间比 = 剩余时间 / 运动时间
73         var temp = remaining / speed || 0;
74         //当前时间比 = 1 - 剩余时间比 -- 即执行到某处时间节点
75         var percent = 1 - temp;
76         //循环运动到时间节点位置
77         for(var  attr in json){
78             nowPlace = (json[attr] - initialPlace[attr]) * percent + initialPlace[attr];
79             if(attr == ‘opacity‘){
80                 obj.style.opacity = nowPlace / 100;
81             }else{
82                 obj.style[attr] = nowPlace + ‘px‘;
83             }
84         }
85         //当前时间与运动时间比为1:1时,说明到达运动终点了,结束定时器,并判断是否有回调函数
86         if(percent == 1){
87             clearInterval(obj.timer);
88             typeof callback == ‘function‘ ? callback() : ‘‘;
89         }
90     },30);
91 }

示例还是基于链式运动的示例进行修改过来了,但是运动函数已经发生了质的变化。因为代码我都有些注释,就不详细解析了。提一个相对比较重要的点,这篇博客相对于前面的博客(运动系列),这篇博客的动画行为主要是受限定的运动时间来控制的,单次运动距离由运动实际运动时间比总(参数设置的时间)运动时间,来决定一次运动距离。通过时间比的方式来控制运动速度,和决定什么时候停止动画。

然后还有一个参数easing没有实现,如果没有这个参数,运动行为就都是匀速执行了,请看下面的改进方式:

 1 //在js全局定义运动行为对象
 2 var easingObj = {
 3     linear: function( p ) {
 4         return p;
 5     },
 6     swing: function( p ) {
 7         return 0.5 - Math.cos( p*Math.PI ) / 2;
 8     },
 9     background:function(k) {
10         if (k < (1 / 2.75)) {
11             return 7.5625 * k * k;
12         } else if (k < (2 / 2.75)) {
13             return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
14         } else if (k < (2.5 / 2.75)) {
15             return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
16         } else {
17             return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
18         }
19     }
20 }
21 //然后在startMove运动方法的形参上添加参数easing;参数位置:第四个参数(索引3)
22 //然后设置默认运动行为或接收设置的运动行为
23 //对象行为 -- 默认:swing(匀速)
24 if(!easing){
25     easing = easingObj.swing;
26 }else{
27     easing = easingObj[easing];
28 }
29 //将运动节点位置那行代码修改
30 //实质是将percend用行为函数包裹起来
31 nowPlace = (json[attr] - initialPlace[attr]) * easing(percent) + initialPlace[attr];

最后调用代码:

oDivArray[0].onclick = function(){
    startMove(this,targetObj,3000,"",function(){
        startMove(oDivArray[1],targetObj,3000,"background");
    });
}

这个方法就完全模仿了jQuery的动画函数animate(),后期我会将这个方法封装,并且会提供缓动函数(easings库)插件接口,缓动函数库手册地址:https://easings.net/zh-cn。运动行为库相对来说还是有些局限性的,所以接下来我会在前面的示例基础上手写弹力效果和撞击效果。一步一步来吧。

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10407696.html

时间: 2024-11-05 12:31:25

原生JavaScript运动功能系列(五):定时定点运动的相关文章

原生JavaScript运动功能系列(三):多物体多值运动

多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素实现,如果将前面封装的动画实现方法同时触发我可以肯定的告诉你会有bug,我们先来写一个示例看看这个bug是什么?示例需求是有三个div同时居于浏览器左侧,当鼠标进入div时,当前div的宽度变宽,鼠标离开时,宽度也已动画状态恢复. //html <div></div> <div&

大前端技术系列:TWA技术+TensorFlow.js =&gt; 集成原生和AI功能的app

大前端技术系列:TWA技术+TensorFlow.js => 集成原生和AI功能的app ( 本文内容为melodyWxy原作,git地址:https://github.com/melodyWxy/twa-tf.js , ) 什么是TWA 简单来讲,TWA(Trusted Web Activity 可信任的网络应用)即: 基于Chrome Custom Tabs,利用谷歌浏览器提供的api,实现强大功能的桌面应用技术. 如果说你对PWA这个概念有所了解,那么TWA的实现就相当于 PWA + 更丰

javascript运动系列第九篇——碰撞运动

× 目录 [1]碰撞检测 [2]无损碰撞 [3]有损碰撞 前面的话 碰撞可以分为碰壁和互碰两种形式,上篇介绍了碰壁运动,本文将从浅入深地介绍碰撞运动的互碰形式 碰撞检测 对于互碰形式的碰撞运动来说,首先要解决的是碰撞检测.对于矩形元素的碰撞检测前面的博文已经详细介绍过,下面主要介绍圆形元素的碰撞检测 矩形元素的碰撞检测利用九宫格分析法,而圆形元素的碰撞检测则简单很多,判断两个圆形元素的半径之和是否大于两个圆形元素的圆心点坐标之间的距离即可 由示意图可知,元素一的圆心位置为(x1,y1),半径为r

原生JavaScript技巧大收集100个

原生JavaScript技巧大收集 1.原生JavaScript实现字符串长度截取function cutstr(str, len) { var temp; var icount = 0; var patrn = /[^\x00-\xff]/; var strre = ""; for (var i = 0; i < str.length; i++) { if (icount < len - 1) { temp = str.substr(i, 1); if (patrn.ex

Apache Kafka系列(五) Kafka Connect及FileConnector示例

Apache Kafka系列(一) 起步 Apache Kafka系列(二) 命令行工具(CLI) Apache Kafka系列(三) Java API使用 Apache Kafka系列(四) 多线程Consumer方案 Apache Kafka系列(五) Kafka Connect及FileConnector示例 一. Kafka Connect简介 Kafka是一个使用越来越广的消息系统,尤其是在大数据开发中(实时数据处理和分析).为何集成其他系统和解耦应用,经常使用Producer来发送消

常见的dom操作----原生JavaScript与jQuery

1.创建元素 文本节点 JavaScript: document.createElement(),只接收一个参数,创建后需要手动将其添加到文档树中,例如: var newDiv = document.createElement("div");if(document.body){ document.body.appendChild(newDiv);}else{ document.documentElement.appendChild(newDiv);} document.createTe

使用原生javascript如何读写css样式?

一说起操作css样式很多人都会想到jQuery的css方法: $(selector).css(name) ,但是有思考过如何使用原生javascript来实现类似的功能么?本文和大家分享的就是使用原生javascript实现css样式相关内容,一起来看看吧,希望对大家学习javascript有所帮助. 大家最熟悉的原生js操作样式的方法非DOM中的Style对象莫属了,但是这个方法只能获取和修改html文档中的内联样式,无法操作非内联样式(内部样式和外部样式表).我通过搜索和整理,总结了使用原生

为什么原生 JavaScript 开发越来越多受欢迎?是否应该跟风用原生JavaScript代替 jQuery等库?

本文标签:  jQuery的作用 原生JavaScript优势 jQuery官网 jQuery处理DOM和跨浏览器 JavaScript新特性 互联网杂谈 随着 JavaScript 本身的完善,越来越多的人开始喜欢使用原生 JavaScript 开发代替各种库,其中不少人发出了用原生 JavaScript 代替 jQuery 的声音.这并不是什么坏事,但也不见得就是好事.如果你真的想把 jQuery从前端依赖库中移除掉,我建议你慎重考虑. 首先 jQuery 是一个第三方库.库存在的价值之一在

原生javascript兼容性问题

1.获取样式表里面的width,border color 之类的css(不是行间) 主要是IE6-7支持currentStyle,标准浏览器支持getComputedStyle; 实例:封装函数 复制代码代码如下: function getStyle(obj,name){ if(obj.currentStyle){ return obj.currentStyle[name]; } else{ return getComputedStyle(obj,false)[name]; } } 调用:get