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

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

定时定点运动示例代码:

 //css
div{
width:100px;
height:100px;
background:red;
position: absolute;
left: 0px;
opacity:;
}
#top{
top: 100px;
}
#bottom{
top: 300px;
}
//html
<div id="top"></div>
<div id="bottom"></div>
//js
var oDivArray = document.getElementsByTagName('div');
var timer = null;
var targetObj = {
width:400,
height:400,
opacity:50,
left:300,
top:200
}
oDivArray[0].onclick = function(){
startMove(this,targetObj,3000,function(){
startMove(oDivArray[1],targetObj,3000);
});
}
function getStyle(obj,attr){
if(window.getComputedStyle){
return window.getComputedStyle(obj,false)[attr];
}else{
return obj.currentStyle[attr];
}
}
//运动方法startMove的参数:
//obj:运动物体;
//json:目标位置,最终样式值(键值对的形式合成的目标位置对象)
//speed:运动时间(指定运动的时间)
//callback:回调函数
function startMove(obj,json,speed,callback){
//初始位置,移动距离,当前位置
var initialPlace = {};
//新的位置(每次运动的目标点)
var nowPlace;
//结束之前的定时器
clearInterval(obj.timer);
//获取当前时间戳
var createTime = function(){
return (+new Date);
}
//动画开始的时间戳
var startTime = createTime();
//初始位置对象
for(var attr in json){
if(attr == 'opacity'){
initialPlace[attr] = Math.round(parseFloat(getStyle(obj,attr))*100);
}else{
initialPlace[attr] = parseInt(getStyle(obj,attr));
}
}
//定时器
obj.timer = setInterval(function(){
//每次变化的时间
//剩余时间 = Math.max(0,运动开始的时间 + 运动执行事件 - 当前时间) -- 当剩余时间为负数时,返回0
var remaining = Math.max(0, startTime + speed - createTime());
//剩余时间比 = 剩余时间 / 运动时间
var temp = remaining / speed || 0;
//当前时间比 = 1 - 剩余时间比 -- 即执行到某处时间节点
var percent = 1 - temp;
//循环运动到时间节点位置
for(var attr in json){
nowPlace = (json[attr] - initialPlace[attr]) * percent + initialPlace[attr];
if(attr == 'opacity'){
obj.style.opacity = nowPlace / 100;
}else{
obj.style[attr] = nowPlace + 'px';
}
}
//当前时间与运动时间比为1:1时,说明到达运动终点了,结束定时器,并判断是否有回调函数
if(percent == 1){
clearInterval(obj.timer);
typeof callback == 'function' ? callback() : '';
}
},30);
}

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

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

 //在js全局定义运动行为对象
var easingObj = {
linear: function( p ) {
return p;
},
swing: function( p ) {
return 0.5 - Math.cos( p*Math.PI ) / 2;
},
background:function(k) {
if (k < (1 / 2.75)) {
return 7.5625 * k * k;
} else if (k < (2 / 2.75)) {
return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
} else if (k < (2.5 / 2.75)) {
return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
} else {
return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
}
}
}
//然后在startMove运动方法的形参上添加参数easing;参数位置:第四个参数(索引3)
//然后设置默认运动行为或接收设置的运动行为
//对象行为 -- 默认:swing(匀速)
if(!easing){
easing = easingObj.swing;
}else{
easing = easingObj[easing];
}
//将运动节点位置那行代码修改
//实质是将percend用行为函数包裹起来
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。运动行为库相对来说还是有些局限性的,所以接下来我会在前面的示例基础上手写弹力效果和撞击效果。一步一步来吧。

相关技术博客参考:

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

  1. 原生JavaScript运动功能系列(四):多物体多值链式运动

    原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现 原生JavaScript运动功能系列(二):缓冲运动 原生JavaScript运动功能系列(三):多物体多值运动 多物体多值链式 ...

  2. 原生JavaScript运动功能系列(二):缓冲运动

    匀速运动实现回顾 缓冲运动剖析 示例实现 方法提取 匀速运动实现回顾及缓冲运动剖析: 在这个系列的上一篇博客中原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现就运动的核心功能组成 ...

  3. 原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现

    在我们日常生活中运动就是必不可少的部分,走路.跑步.打篮球等.在网页交互设计上运动也是必不可少的部分,创建的网站交互设计运动模块有轮播图,下拉菜单,还有各种炫酷的游戏效果都跟运动密切相关.所以很重要, ...

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

    多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素 ...

  5. javascript学习-原生javascript的小特效(多个运动效果整理)

    以下代码就不详细解析了,在我之前的多个运动效果中已经解析好多次了,重复的地方这里就不说明了,有兴趣的童鞋可以去看看之前的文章<原生javascript的小特效> <!DOCTYPE ...

  6. javascript学习-原生javascript的小特效(简单的运动效果)

    前些日子看了个视频所以就模仿它的技术来为大家做出几个简单的JS小特效 一:运动特效(主要是通过改变元素的left,right,height,width,opacity来达到运动的效果) 我们今天做一个 ...

  7. javascript学习-原生javascript的小特效(多物体运动效果)

    前些日子看了个视频所以就模仿它的技术来为大家做出几个简单的JS小特效 今天为大家做的是多个物体的运动效果, 1:HTML <body> <ul>       <li> ...

  8. javascript类继承系列五(其他方式继承)

    除了前面学习的三种继承外,还有另外三种:原型继承寄生继承,寄生组合继承都是以: function object(o) { function F() { } F.prototype = o; retur ...

  9. 原生javascript写自己的运动库(匀速运动篇)

    网上有很多JavaScript的运动库,这里和大家分享一下用原生JavaScript一步一步写一个运动函数的过程,如读者有更好的建议欢迎联系作者帮助优化完善代码.这个运动函数完成后,就可以用这个运动函 ...

随机推荐

  1. [USACO12MAR] 花盆Flowerpot

    类型:二分+单调队列 传送门:>Here< 题意:给出$N$个点的坐标,要求根据$x$轴选定一段区间$[L,R]$,使得其中的点的最大与最小的$y$值之差$\geq D$.求$Min\{R ...

  2. 基于Thinkphp5.0 小程序登录插件应用

    资源连接: wulongtao/think-wxminihelper 具体怎么安装,不介绍了,有不懂再问我吧: 主要重点如下: wepy:index.wpy this.$parent.getUserI ...

  3. 七牛云 qshell 使用

    七牛云 qshell 控制台工具上传 命令:qshell fput another1 demo.txt /users/tianyang/demo.txt ======================= ...

  4. HNOI2019 游记

    HNOI2019 游记 Day 0 其实考前几天,心里还是挺慌的.结果最后 Day 0 的时候,因为种种原因反而释然了.也许是觉得,在这一步退役,也没有什么好害怕的吧. OI 本身就是一项偶然性太大的 ...

  5. 【HDU1848】Fibonacci again and again(博弈论)

    [HDU1848]Fibonacci again and again(博弈论) 题面 Hdu 你有三堆石子,每堆石子的个数是\(n,m,p\),你每次可以从一堆石子中取走斐波那契数列中一个元素等数量的 ...

  6. 【LOJ#6060】Set(线性基)

    [LOJ#6060]Set(线性基) 题面 LOJ 题解 好题啊QwQ. 首先\(x1\oplus x2=s\)是定值.而\(s\)中假设某一位上是\(1\),则\(x1,x2\)上必定有一个是\(1 ...

  7. [luogu5004]专心OI - 跳房子【矩阵加速+动态规划】

    传送门:https://www.luogu.org/problemnew/show/P5004 分析 动态规划转移方程是这样的\(f[i]=\sum^{i-m-1}_{j=0}f[j]\). 那么很明 ...

  8. Linux及Windows查看占用端口的进程

    想必大家在部署环境启动服务的时候,会遇到服务起不起来的问题,看日志,说是端口被占用了. 有的时候,我们不想改端口,那么,就需要去查看到底是哪个应用把这个端口给占用了,然后干掉它即可. 下面分别列举li ...

  9. LOJ#6284. 数列分块入门 8

    分块的时候开一个数组标记这个区间是不是都是一样颜色的部分,如果是的话,我后面的查询,更新部分就可以直接整块操作,对于不是不全部都一样颜色的块在具体进到快里面去暴力. 在更新的时候对边上的两个不完整的块 ...

  10. 【php】php实现数组分块

    有时候需要将一个大数组按一定大小分块,那么可以实现这个功能,代码如下: /** * @param array $arr * @param int $size <p> * @param bo ...