JavaScript动画篇之缓冲运动

今天我来谈谈JS中的动画课题,无可厚非,这是一个很酷的话题。 
想一想,当我们讨论完了这节,我们就可以做出漂亮的渐变动画,包括透明度的设置 
首先,我们来看看动画的基础 
以下是一个按钮和div,当我们点击按钮时,div移动 
HTML部分:

<!DOCTYPE html>
<html>
<meta charset="utf-8"/>
<head>
<link rel="stylesheet" type="text/css" href="dome.css"/>
</head>
<body>
<input type="button" value="按钮" id="btn"/>
<div id="box">box</div>
<div id="container"></div>
<script src="../base.js"></script>
<script src="../tool.js"></script>
<script src="dome.js"></script> 
</body>
</html>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

CSS部分:

body {
    margin:0px;
    padding:0px;
}
#box {
    position : absolute;
    width : 100px;
    height : 100px;
    background : red;
    left : 100px;
    top : 100px;
}
#container {
    width : 300px;
    height : 500px;
    background: #ccc;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

JS部分:

// 跨浏览器获取css样式
function getStyle(element, attr) {
    var value = 0;
    if (typeof window.getComputedStyle != 'undefined') {    // W3C
        value = window.getComputedStyle(element, null)[attr];
    } else if (typeof element.currentStyle != 'undefined') {    // IE
        value = element.currentStyle[attr];
    }
    return value;
}
// 加载DOM
(function () {
    var div = document.getElementById("box");
    $("#btn").click(function () {
        var timer = setInterval(function () {
            element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
            if (parseInt(getStyle(div, "left")) >= 300) clearInterval(timer);
            document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
        }, 30);
    });
})();

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这样我们,就可以简单的通过单击按钮使得DIV运动起来,实现简单的动画 
接下来,我们将这个简单的动画封装一下下

Base.prototype.animate = function (attr, target, step, t) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        var element = this.elements[i];
        var timer = setInterval(function () {
            element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
            if (parseInt(getStyle(element, attr)) >= target)    clearInterval(timer);
            document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
        }, t);
    }
    return this;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

前台调用部分:

(function () {
    var div = document.getElementById("box");
    $("#btn").click(function () {
        $("#box").animate("left", 300, 10, 30);
    });
})();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

由于animate()方法的参数计较多,容易混淆,我们该为传个对象, 
并且加入增量alter

Base.prototype.animate = function (obj) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        var element = this.elements[i];
        var attr = obj.attr !== undefined ? obj.attr : "left";
        var start = obj.attr !== undefined ? obj.attr : parseInt(getStyle(element, attr));
        // 当alter和target同时存在时,忽略alter
        var alter = obj.alter;
        var target = obj.target;
        if (alter !== undefined && target === undefined) {
            target = start + alter;
        } else if (alter === undefined && target === undefined) {
            throw new Error("增量alter或者目标量target两个值必须填一个");
        }
        var step = obj.step !== undefined ? obj.step : 10;
        var t = obj.t !== undefined ? obj.t : 30;

        var timer = setInterval(function () {
            element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
            if (parseInt(getStyle(element, attr)) >= target)    clearInterval(timer);
            document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
        }, t);
    }
    return this;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

前台调用:

(function () {
    var div = document.getElementById("box");
    $("#btn").click(function () {
        $("#box").animate({
            attr : "left",
            start : 100,
            alter : 900,    // 当alter和target同时存在时,忽略alter
            target : 300,
            step : 10,
            t : 30
        });
    });
})();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

问题:当我们将step设置为7的时候,div到达303才能停止,这显然不是我们想要的结果 
因此我们在div.style.left >= target时,让其直接等于target

window.timer = setInterval(function () {
    if (parseInt(getStyle(element, attr)) >= target) {
        element.style[attr] = target + 'px';
        clearInterval(timer);
    } else {
        element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
    }
    document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
}, t);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

问题:当div运动到303时,它会自动调回300,这时会有一点卡的感觉 
因此我们想要div在296的时候,直接到300,这样更符合。 
当div的left属性与target的绝对值小于等于step步长时,我们直接让其等于target

var t = obj.t !== undefined ? obj.t : 30;
window.timer = setInterval(function () {
    if (Math.abs(parseInt(getStyle(element, attr)) - target) <= step) {
        element.style[attr] = target + 'px';
        clearInterval(timer);
    } else {
        element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
    }
    document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
}, t);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

问题:当我们不停的单击按钮时,就会不停的触发事件,导致不停的调用定时器,使得div运动的速度越来越快 
因此,我们需要将timer放在全局变量中,且在定时器每次被调用时先清除一下

var timer = null;       // 将定时器变量放在全局中
Base.prototype.animate = function (obj) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        var element = this.elements[i];
        var attr = obj.attr !== undefined ? obj.attr : "left";
        var start = obj.attr !== undefined ? obj.attr : parseInt(getStyle(element, attr));
        // 当alter和target同时存在时,忽略alter
        var alter = obj.alter;
        var target = obj.target;
        if (alter !== undefined && target === undefined) {
            target = start + alter;
        } else if (alter === undefined && target === undefined) {
            throw new Error("增量alter或者目标量target两个值必须填一个");
        }
        var step = obj.step !== undefined ? obj.step : 10;
        var t = obj.t !== undefined ? obj.t : 30;
        clearInterval(timer);       // 每次才定时器干活前,先把以前的定时器清除掉,防止重复调用
        timer = setInterval(function () {
            if (Math.abs(parseInt(getStyle(element, attr)) - target) <= step) {
                element.style[attr] = target + 'px';
                clearInterval(timer);
            } else {
                element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
            }
            document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
        }, t);
    }
    return this;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

问题:当我们想要让div向左移动时,我们需要将step设置为-7, 
且当div的left属性与target的差值小于等于step步的绝对值时,我们让其直接等于target

timer = setInterval(function () {
    if (step > 0 && Math.abs(parseInt(getStyle(element, attr)) - target) <= step) {
        element.style[attr] = target + 'px';
        clearInterval(timer);
    // 向左向下移动
    } else if (step < 0 && parseInt(getStyle(element, attr)) - target <= Math.abs(step)) {
        element.style[attr] = target + 'px';
        clearInterval(timer);
    }else {
        element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
    }
    document.getElementById("container").innerHTML += getStyle(element, attr) + "<br/>";
}, t);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

前台调用

(function () {
    var div = document.getElementById("box");
    $("#btn").click(function () {
        $("#box").animate({
            attr : "top",
            start : 100,
            target : 0,
            step : -7,
            t : 30
        });
    });
})();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

问题:我们设置step为负时,会感觉很别扭,我们需要让其为正 
因此当div的left属性大于target时,我们让step取负

if (parseInt(getStyle(element, attr)) >= target) step = - step;
 
 
  • 1

前台调用

$("#box").animate({
    attr : "left",
    start : 100,
    target : 0,
    step : 7,       // 还是为正
    t : 30
});
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题:当div的目标值到达了300,我们再次单击按钮时,它就不动了 
因此,我们需要设置:当div到达300了,我们让它重置为start,这样它可以重新运动 
element.style[attr] = start + ‘px’; 
问题:当我们前台调用attr属性为left时,这样不太清晰,我们用x表示left, 
y表示top,w表示width,x表示height

var attr = obj.attr === 'x' ? 'left' : obj.attr === 'y' ? 'top' :
    obj.attr === 'w' ? 'width' : obj.attr === 'h' ? 'height' : "left";
 
 
  • 1
  • 2

前台调用

$("#box").animate({
    attr : "w",
    start : 100,
    target : 300,
    step : 7,
    t : 30
});
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题:我们需要缓冲运动,这样就使得运动更加的逼真 
分析:缓冲运动的意思就是随着div的left属性值与target目标点的差值变小,运动的速度(speed)也逐渐变小

var timer = null;
Base.prototype.animate = function (obj) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        var element = this.elements[i];
        var attr = obj.attr === 'x' ? 'left' : obj.attr === 'y' ? 'top' :
                   obj.attr === 'w' ? 'width' : obj.attr === 'h' ? 'height' : "left";
        var start = obj.start !== undefined ? obj.start : parseInt(getStyle(element, attr));
        // 当alter和target同时存在时,忽略alter
        var alter = obj.alter;
        var target = obj.target;
        if (alter !== undefined && target === undefined) {
            target = start + alter;
        } else if (alter === undefined && target === undefined) {
            throw new Error("增量alter或者目标量target两个值必须填一个");
        }
        var step = obj.step !== undefined ? obj.step : 10;
        if (start >= target) step = - step;
        var speed = obj.speed !== undefined ? obj.speed : 6;
        var type = obj.type === 0 ? "contant" : obj.type === 1 ? "buffer" : "buffer";
        element.style[attr] = start + 'px';
        var t = obj.t !== undefined ? obj.t : 30;

        clearInterval(timer);
        timer = setInterval(function () {
            // 缓冲运动
            if (type === "buffer") {
                var temp = (target - parseInt(getStyle(element, attr))) / speed;
                step = step > 0 ? Math.ceil(temp) : Math.floor(temp);
            }
            // 因为step的范围不可能为0
            if (step > 0 && Math.abs(parseInt(getStyle(element, attr)) - target) <= step) {
                getTarget();
            } else if (step < 0 && parseInt(getStyle(element, attr)) - target <= Math.abs(step)) {
                getTarget();
            }else {
                element.style[attr] = parseInt(getStyle(element, attr)) + step + "px";
            }
            document.getElementById("container").innerHTML += step + "<br/>";
        }, t);
        function getTarget () {
            element.style[attr] = target + 'px';
            clearInterval(timer);
        }
    }
    return this;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

前台调用

(function () {
    var div = document.getElementById("box");
    $("#btn").click(function () {
        $("#box").animate({
            attr : "x",
            start : 100,
            target : 300,
            step : 7,
            speed : 5,
            t : 30,
            type : 1
        });
    });
})();
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript动画小游戏是一种使用JavaScript编程语言开发的小型游戏。这种游戏通常具有简单的规则和操作,但是通过使用JavaScript动画功能,可以给玩家带来更加丰富和有趣的游戏体验。 在这种类型的游戏中,开发者可以使用JavaScript中的动画库或自定义动画函数来创建各种动画效果。比如,可以通过改变元素的位置、大小、颜色等属性来实现平滑的动画过渡。这种动画效果的应用可以使得游戏场景更加生动和沉浸式。 除了动画效果,JavaScript动画小游戏还可以包括玩家的操作,比如点击、拖拽等。通过监听用户的交互事件,可以触发相应的动画效果或游戏行为,增加游戏的交互性和挑战性。 例如,一个简单的JavaScript动画小游戏可以是一个跳跃的小球避开障碍物的游戏。玩家控制小球的移动,通过点击屏幕或按键来让小球跳起,同时要躲避障碍物。通过改变小球的位置和障碍物的出现位置,可以创建出具有挑战性和变化性的游戏体验。 除了开发过程中的动画效果和交互操作,JavaScript动画小游戏还可以通过添加音效、计分系统、关卡设置等功能来增加游戏的趣味性和可玩性。 总之,JavaScript动画小游戏是一种利用JavaScript编程语言创建的小型游戏,通过运用动画效果和交互操作,为玩家提供丰富,有趣和具有挑战性的游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值