前端技术分享-码匠 极客编程技术分享

您当前位于:jQuery与类库搭建 ——> JavaScript弹性框架(摩擦力视觉感)的实现方法(下)

JavaScript弹性框架(摩擦力视觉感)的实现方法(下)

2015/06/28 10:40:41 | 作者:HTML5学堂(码匠) | 分类:jQuery与类库搭建 | 关键词:框架开发,弹性运动,缓冲运动

一步步教你弹性框架-下篇

HTML5学堂:本文继续为大家讲解弹性框架,在前两篇文章当中,我们从最基本的来回运动,讲解到缓冲运动、有摩擦力的运动。基本实现了弹性动画效果。今天我们主要来进行函数的封装与优化。

第六步 运动功能函数封装

首先在一个元素点击时,应当执行一个功能函数,这个功能函数我们将其独立出来,作为一个全局的函数而存在,从而实现多次调用。之后我们为了便于控制,需要“变量换常量”、“使用参数控制传入”。在整个功能当中,要发生位置变化的元素是不确定的;每次的终点值以及起点值也是不确定的。对于到底要通过哪种属性让元素变化(之前我们采用的是margin-left,如果使用定位也是可以采用left的)。因此,我们至少需要采用3个参数来辅助我们效果的完成。

完成至第五步的代码

  1. var btn = document.getElementById("btn");    // 获取控制按钮
  2. var move = document.getElementById("move");    // 获取运动块
  3. var timer = null;    // 初始化一个计时器
  4. var speed = 0;    // 初始化一个速度
  5. var startVal = parseInt(getStyle(move, "marginLeft"));    // 获取初始位置
  6. var targetVal = 600;    // 用于存储目标值
  7.  
  8. btn.onclick = function () {
  9.     timer = setInterval(function(){
  10.         speed += (targetVal - startVal) / 40;
  11.         speed *= 0.95;
  12.         startVal += speed;
  13.         
  14.         if (Math.abs(speed) < 1 && Math.abs(startVal - targetVal) < 1) {
  15.             clearInterval(timer);
  16.             startVal = targetVal;
  17.         };
  18.  
  19.         move.innerHTML = "速度:" + speed + "当前位置:" + startVal;    // 测试用代码-便于理解
  20.         move.style.marginLeft = startVal + "px";    // 通过修改marginLeft实现块向右运动
  21.     }, 24);
  22. }

PS:对于基本结构与样式代码,在我们前一篇文章——一步步教你弹性运动框架(上)中有书写,可直接点击查看。

修改后的代码

  1. var btn = document.getElementById("btn");    // 获取控制按钮
  2. var move = document.getElementById("move");    // 获取运动块
  3. var timer = null;    // 初始化一个计时器
  4. var speed = 0;    // 初始化一个速度
  5.  
  6. btn.onclick = function(){
  7.     bounce(move, "marginLeft", 600)
  8. }
  9. function bounce(ele, prop, targetVal) {
  10.     var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
  11.     timer = setInterval(function(){
  12.         speed += (targetVal - startVal) / 40;
  13.         speed *= 0.95;
  14.         startVal += speed;
  15.         
  16.         if (Math.abs(speed) < 1 && Math.abs(startVal - targetVal) < 1) {
  17.             clearInterval(timer);
  18.             startVal = targetVal;
  19.         };
  20.  
  21.         ele.innerHTML = "速度:" + speed + "当前位置:" + startVal;    // 测试用代码-便于理解
  22.         ele.style[prop] = startVal + "px";    // 通过修改marginLeft实现块向右运动
  23.     }, 24);
  24. }

欢迎沟通交流~HTML5学堂

第七步 优化计时器与速度

和我们课上讲解到的动画框架是类似的,在一个页面当中,可能存在着两个或以上的元素共用一个动画功能函数,那么此时计时器以及速度就绝对不能够共用。因此,我们需要将timer以及speed这两个全局变量调整为局部变量(以对象.属性、对象.方法的方式进行书写)

调整代码如下:

  1. var btn = document.getElementById("btn");    // 获取控制按钮
  2. var move = document.getElementById("move");    // 获取运动块
  3.  
  4. btn.onclick = function(){
  5.     bounce(move, "marginLeft", 600)
  6. }
  7. function bounce(ele, prop, targetVal) {
  8.     var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
  9.     ele.speed = 0;
  10.     ele.timer = setInterval(function(){
  11.         ele.speed += (targetVal - startVal) / 40;
  12.         ele.speed *= 0.95;
  13.         startVal += ele.speed;
  14.         
  15.         if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
  16.             clearInterval(ele.timer);
  17.             startVal = targetVal;
  18.         };
  19.  
  20.         ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
  21.         ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
  22.     }, 24);
  23. }
  24.  

第八步 防止计时器叠加以及最后的优化

防止计时器叠加

当使用鼠标不断点击按钮时,我们并没有检测当前是否有计时器,因此为了防止不断的点击而造成的计时器叠加,我们需要进行计时器的检测。

一种方式是在每次运行函数过程中,检测ele.timer是否存在,如果存在则清除。但是这种方式会导致一些问题,在多次点击时,虽然并不会停不下来或造成抖动,但是会对“弹簧”的整体效果产生影响,让人感觉有些卡顿(相当于每次点击之后都是重新一个动画,而速度不同会让人感觉不流畅)

因此,我们采用另一种方式,用一个布尔值判断当前是否已经点击过按钮,如果点击过,则不再执行,如果还没有点击过,则执行运动功能函数。一起来看代码:

  1. var btn = document.getElementById("btn");    // 获取控制按钮
  2. var move = document.getElementById("move");    // 获取运动块
  3. btn.judge = false;
  4. btn.onclick = function(){
  5.     if (btn.judge == false) {
  6.         bounce(move, "marginLeft", 600);
  7.         btn.judge = true;
  8.     };
  9. }
  10. function bounce(ele, prop, targetVal) {
  11.     var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
  12.     ele.speed = 0;
  13.     ele.timer = setInterval(function(){
  14.         ele.speed += (targetVal - startVal) / 40;
  15.         ele.speed *= 0.95;
  16.         startVal += ele.speed;
  17.         
  18.         if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
  19.             clearInterval(ele.timer);
  20.             startVal = targetVal;
  21.         };
  22.  
  23.         ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
  24.         ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
  25.     }, 24);
  26. }

最后的优化

终于到最后一步了,先来庆祝一下~然后呢,我们需要稍微调整一下,让整个弹簧式的效果变得更舒服些,整个地方需要调整步长(原来我使用的是40)以及摩擦力的值(原来我使用的是0.95),分别调整为步长5以及0.7的摩擦力值,这个时候弹簧效果的速度会比较快且不会太多次的来回往复运动。(这个数字是测试出来的,各位也可以根据情况自行修改)

最后的最后,千万不要忘记我们的代码注释,良好的代码注释才会让我们日后更好的维护和修改。

  1. var btn = document.getElementById("btn");    // 获取控制按钮
  2. var move = document.getElementById("move");    // 获取运动块
  3. btn.judge = false;
  4. btn.onclick = function(){
  5.     if (btn.judge == false) {
  6.         bounce(move, "marginLeft", 600);
  7.         btn.judge = true;
  8.     };
  9. }
  10.  
  11. /*
  12. * 功能:弹性运动框架(需要注意,还需要在事件绑定时进行细节处理)
  13. * 参数:ele是元素对象,prop是样式属性,targetVal表示要达到的目标值
  14. * 调用demo:bounce(move, "marginLeft", 600);
  15. * 绑定demo:
  16.     btn.judge = false;
  17.     btn.onclick = function(){
  18.         if (btn.judge == false) {
  19.             bounce(move, "marginLeft", 600);
  20.             btn.judge = true;
  21.         };
  22.     }
  23. * author:HTML5学堂
  24. */
  25. function bounce(ele, prop, targetVal) {
  26.     var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
  27.     ele.speed = 0;
  28.     ele.timer = setInterval(function(){
  29.         ele.speed += (targetVal - startVal) / 5;
  30.         ele.speed *= 0.7;
  31.         startVal += ele.speed;
  32.         
  33.         if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
  34.             clearInterval(ele.timer);
  35.             startVal = targetVal;
  36.         };
  37.  
  38.         ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
  39.         ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
  40.     }, 24);
  41. }

经过三篇文章,终于算是把我们的弹性框架讲解完成了~还是那句话,慢慢来,重要的是思路,知识要活学活用。

欢迎沟通交流~HTML5学堂

微信公众号,HTML5学堂,码匠,原创文章,WEB前端,技术分享

HTML5学堂

原创前端技术分享

HTML5学堂,HTML5,WEB,前端,视频课程,技术视频,学习视频,面试,JS

原创视频课程

用心打造精品课程

微信小程序,决胜前端,面试题,面试题集合,前端,HTML5,真题

小程序-决胜前端

前端面试题宝库

原创书籍,学习书籍,书籍推荐,HTML5布局之路,HTML5,WEB前端

HTML5布局之路

非传统模式讲解前端