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

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

定时定点运动示例代码:

 //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. Verilog定义计算位宽的函数clogb2

    在很多情况下要计算输入输出的位宽,比如你写一个8*8的ram,那么地址需要三位去表示,那么这个函数的方便就体现出来了,你需要使用函数定义就好了,如果对于多文件可以包含定义的文件: 如果你的DEPTH是 ...

  2. Eslint相关知识和配置大全

    ESLint最初是由Nicholas C. Zakas 于2013年6月创建的开源项目.它的目标是提供一个插件化的javascript代码检测工具. 代码检查是一种静态的分析,常用于寻找有问题的模式或 ...

  3. Hdoj 2044.一只小蜜蜂... 题解

    Problem Description 有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行.请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数. 其中,蜂房的结构如下所示. Input 输入数据的第一 ...

  4. 【BZOJ5417】[NOI2018]你的名字(线段树,后缀自动机)

    [BZOJ5417][NOI2018]你的名字(线段树,后缀自动机) 题面 BZOJ 洛谷 题解 首先考虑\(l=1,r=|S|\)的做法,对于每次询问的\(T\)串,暴力在\(S\)串的\(SAM\ ...

  5. css- @media @font-face 的理解

    在我的博客园定制的css中有2个之前没有遇到的csss属性@font-face @media @media 在css文件中的使用如下 ` @media screen and (max-width: 1 ...

  6. 使用ss命令对tcp连接数和状态的监控性能优化

    之前对tcp的监控采用netstat命令,发现在服务器繁忙的时候效果不理想,这个命令占用大量的cpu有时候高达90%以上,可能会导致业务的不稳定,所以改用ss命令对脚本进行优化 对tcp连接数和状态的 ...

  7. 20165223《Java程序设计》第七周Java学习总结

    教材学习内容总结 第11章-JDBC与MySQL数据库 要点 MySQL数据库管理系统 连接MySQL数据库 查询操作(基础) 更新.添加.删除(基础) 预处理语句(重点) 通用查询(难点) 事务 笔 ...

  8. redux源码解析-redux的架构

    redux很小的一个框架,是从flux演变过来的,尽管只有775行,但是它的功能很重要.react要应用于生成环境必须要用flux或者redux,redux是flux的进化产物,优于flux. 而且r ...

  9. 工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)

    分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.工厂模式在<Java 与模式>中分为三类:1)简单工厂模式(Simple Facto ...

  10. 【洛谷P1903】数颜色

    题目大意:给定一个长度为 N 的序列,每个点有一个颜色.现给出 M 个操作,支持单点修改颜色和询问区间颜色数两个操作. 题解:学会了序列带修改的莫队. 莫队本身是不支持修改的.带修该莫队的本质也是对询 ...