原生JavaScript运动功能系列(五):定时定点运动
- 原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现
- 原生JavaScript运动功能系列(二):缓冲运动
- 原生JavaScript运动功能系列(三):多物体多值运动
- 原生JavaScript运动功能系列(四):多物体多值链式运动
这篇博客剖析一个问题,就是怎么实现将元素指定时间运动到目标位置?前面的博客都是在处理运动行为,没有对运动时间做任何限定,只是因为清晰的分析运动行为和实现原理,要想一个动画函数具备健全的功能,并且可以随意使用,通过参数设定动画执行时间是非常有必要的一个设计。
在前面任意一种运动函数内,实质上只有一个变量,这个变量就是运动距离(缓冲运动中添加了因数),当运动距离变大时,运动时间就会变长,动画停止条件是由坐标来决定的。当指定运动时间时,运动速度就会同时受到运动距离和运动时间的限制,动画停止条件也是由时间来控制。
定时定点运动示例代码:
//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运动功能系列(五):定时定点运动的更多相关文章
- 原生JavaScript运动功能系列(四):多物体多值链式运动
原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现 原生JavaScript运动功能系列(二):缓冲运动 原生JavaScript运动功能系列(三):多物体多值运动 多物体多值链式 ...
- 原生JavaScript运动功能系列(二):缓冲运动
匀速运动实现回顾 缓冲运动剖析 示例实现 方法提取 匀速运动实现回顾及缓冲运动剖析: 在这个系列的上一篇博客中原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现就运动的核心功能组成 ...
- 原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现
在我们日常生活中运动就是必不可少的部分,走路.跑步.打篮球等.在网页交互设计上运动也是必不可少的部分,创建的网站交互设计运动模块有轮播图,下拉菜单,还有各种炫酷的游戏效果都跟运动密切相关.所以很重要, ...
- 原生JavaScript运动功能系列(三):多物体多值运动
多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素 ...
- javascript学习-原生javascript的小特效(多个运动效果整理)
以下代码就不详细解析了,在我之前的多个运动效果中已经解析好多次了,重复的地方这里就不说明了,有兴趣的童鞋可以去看看之前的文章<原生javascript的小特效> <!DOCTYPE ...
- javascript学习-原生javascript的小特效(简单的运动效果)
前些日子看了个视频所以就模仿它的技术来为大家做出几个简单的JS小特效 一:运动特效(主要是通过改变元素的left,right,height,width,opacity来达到运动的效果) 我们今天做一个 ...
- javascript学习-原生javascript的小特效(多物体运动效果)
前些日子看了个视频所以就模仿它的技术来为大家做出几个简单的JS小特效 今天为大家做的是多个物体的运动效果, 1:HTML <body> <ul> <li> ...
- javascript类继承系列五(其他方式继承)
除了前面学习的三种继承外,还有另外三种:原型继承寄生继承,寄生组合继承都是以: function object(o) { function F() { } F.prototype = o; retur ...
- 原生javascript写自己的运动库(匀速运动篇)
网上有很多JavaScript的运动库,这里和大家分享一下用原生JavaScript一步一步写一个运动函数的过程,如读者有更好的建议欢迎联系作者帮助优化完善代码.这个运动函数完成后,就可以用这个运动函 ...
随机推荐
- 牛客小白月赛12 H(dfs序+线段树),F(分块思想+bit),J(二分)
H 华华和月月种树 链接:https://ac.nowcoder.com/acm/contest/392/H 思路:先得到整棵树最终的形态,在这棵树上进行三种操作,用dfs跑下,第二种操作就直接对最终 ...
- PSR-0 规范实例讲解 -- php 自动加载
PSR-0规范 [1]命名空间必须与绝对路径一致 [2]类名首字母必须大写 [3]除去入口文件外,其他“.php”必须只有一个类 [4]php类文件必须自动载入,不采用include等 [5]单一入口 ...
- gogs : 添加 ssh An error has occurred : addKey: fail to parse public key: exec: "ssh-keygen": executable file not found in %PATH% - exec: "ssh-keygen": executable file not found in %PATH%
服务器上缺少配置 ssh-keygen.exe的 环境变量.git的环境变量 在path 环境变量加上.重启gogs服务
- 自学Python之路-Python核心编程
自学Python之路-Python核心编程 自学Python之路[第六回]:Python模块 6.1 自学Python6.1-模块简介 6.2 自学Python6.2-类.模块.包 ...
- 解决忘记mysql中的root用户密码问题
如果忘了数据库中的root密码,无法登陆mysql. 解决步骤: 1. 使用“--skip-grant-tables”启动数据库 ~]#systemctl stop mysql ~]#mysqld_s ...
- Wireshark:couldn't run dumpcap in child process(附带Linux下探索过程)
之前都是直接使用Kali里面安装好的Wireshark和Win下的,Ubuntu的来个小计 PS:解决方法不重要,我觉得更重要的是这个摸索的过程 解决方法 # 安装wireshark sudo apt ...
- vue学习笔记(二)- 数据绑定、列表渲染、条件判断
vue的数据绑定和列表渲染的造轮子 GitHub:八至 作者:狐狸家的鱼 双向数据绑定 Vue中数据的双向绑定-v-model 数据->页面 页面->数据 适用:input.select. ...
- GNOME 3.28 启用桌面图标
原由 GNOME 3.28合并了移除桌面图标支持 Nautilus从此不在支持桌面图标,直到找到新的解决方案 Issues地址:https://gitlab.gnome.org/GNOME/nauti ...
- [luogu3388][割点]
题目链接 思路 真板子题.割点是指在一个无向图中,删去之后图将不再连通的点.可以用tarjan算法求.根据割点有两种情况,一种是根,一种是非根.如果不是根的就去判断在tarjan的时候当前节点所能到的 ...
- CF1129D Isolation(分块+DP)
一个很显然的DP方程式:f[i]=Σf[j],其中j<i且在[j+1,i]中出现1次的数不超过k个 乍一看挺神仙的,只会O(n^2),就是对于每个位置从后向前扫一遍,边扫边统计出现1次的数的个数 ...