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

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

相关阅读:

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

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

第六步 运动功能函数封装

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

完成至第五步的代码

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

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

修改后的代码

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

第七步 优化计时器与速度

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

调整代码如下:

var btn = document.getElementById("btn");    // 获取控制按钮
var move = document.getElementById("move");    // 获取运动块
 
btn.onclick = function(){
    bounce(move, "marginLeft", 600)
}
function bounce(ele, prop, targetVal) {
    var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
    ele.speed = 0;
    ele.timer = setInterval(function(){
        ele.speed += (targetVal - startVal) / 40;
        ele.speed *= 0.95;
        startVal += ele.speed;
 
        if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
            clearInterval(ele.timer);
            startVal = targetVal;
        };
 
        ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
        ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
    }, 24);
}

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

防止计时器叠加

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

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

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

var btn = document.getElementById("btn");    // 获取控制按钮
var move = document.getElementById("move");    // 获取运动块
btn.judge = false;
btn.onclick = function(){
    if (btn.judge == false) {
        bounce(move, "marginLeft", 600);
        btn.judge = true;
    };
}
function bounce(ele, prop, targetVal) {
    var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
    ele.speed = 0;
    ele.timer = setInterval(function(){
        ele.speed += (targetVal - startVal) / 40;
        ele.speed *= 0.95;
        startVal += ele.speed;
 
        if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
            clearInterval(ele.timer);
            startVal = targetVal;
        };
 
        ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
        ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
    }, 24);
}

最后的优化

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

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

var btn = document.getElementById("btn");    // 获取控制按钮
var move = document.getElementById("move");    // 获取运动块
btn.judge = false;
btn.onclick = function(){
    if (btn.judge == false) {
        bounce(move, "marginLeft", 600);
        btn.judge = true;
    };
}
 
/*
* 功能:弹性运动框架(需要注意,还需要在事件绑定时进行细节处理)
* 参数:ele是元素对象,prop是样式属性,targetVal表示要达到的目标值
* 调用demo:bounce(move, "marginLeft", 600);
* 绑定demo:
    btn.judge = false;
    btn.onclick = function(){
        if (btn.judge == false) {
            bounce(move, "marginLeft", 600);
            btn.judge = true;
        };
    }
* author:HTML5学堂
*/
function bounce(ele, prop, targetVal) {
    var startVal = parseInt(getStyle(ele, prop));    // 获取初始位置
    ele.speed = 0;
    ele.timer = setInterval(function(){
        ele.speed += (targetVal - startVal) / 5;
        ele.speed *= 0.7;
        startVal += ele.speed;
 
        if (Math.abs(ele.speed) < 1 && Math.abs(startVal - targetVal) < 1) {
            clearInterval(ele.timer);
            startVal = targetVal;
        };
 
        ele.innerHTML = "速度:" + ele.speed + "当前位置:" + startVal;    // 测试用代码-便于理解
        ele.style[prop] = startVal + "px";    // 通过修改属性值实现块的运动
    }, 24);
}

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

原文发布于微信公众号 - HTML5学堂(h5course-com)

原文发表时间:2016-01-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大前端开发

从编程小白到全栈开发:一个简易纯前端计算器

在前文中,我给大家介绍了在JS全栈开发中前端和后端的概念,如果你有了一种茅塞顿开的感觉,恭喜你,你骨骼清奇,是个当程序猿的好苗子。

683
来自专栏彭湖湾的编程世界

【CSS/JS】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势

写前端UI的朋友们也许都遇到过这样的问题:我们需要实现这样一个需求,在一个父级元素中隐藏一个可能过长的文本: 这个文本可能是单行的: ? 也可能是多行的: ? ...

1938
来自专栏菩提树下的杨过

解决JQuery中的ready函数冲突

jQuery确实是一个提高前端开发效率的好框架(虽然很多大牛们都说它效率不咋地),但是用好它有时候并不容易,也许你也遇到过以下情况: 一个aspx页面通常可以包...

1778
来自专栏coding for love

CSS进阶06-相对定位Relative Positioning

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

542
来自专栏章鱼的慢慢技术路

使用3ds Max制作简单卧室

1913
来自专栏拂晓风起

JS:指定FPS帧频,requestAnimationFrame播放动画

1002
来自专栏全沾开发(huā)

总结CSS3新特性(颜色篇)

总结CSS3新特性(颜色篇) 颜色: CSS3新增加了hsl(), hsla(), rgb(),rgba()四个函数来创建color值...

33212
来自专栏Coco的专栏

不可思议的纯CSS导航栏下划线跟随效果

1123
来自专栏点滴积累

使用bokeh-scala进行数据可视化(2)

目录 前言 几种高级可视化图表 总结 一、前言        之前已经简单介绍过一次如何使用Bokeh-scala进行数据可视化(见使用bokeh-scala进...

3377
来自专栏前端小作坊

CSS3着重符及其fallback

在中文里面,我们一般会在文字下方加上圆形符号。在日语中会在文字上方加上小顿号。在CSS3中如下属性可以控制着重符号:

652

扫描关注云+社区