前端有几种实现动画的方式?

1,043 阅读2分钟

最近把一年前实现过的动画组件整理了一遍,同时也想把相关的这个问题:"前端有几种实现动画的方式?" 的理解分享给大家;

我整理了如下的6种方式,接下来我们以最简单的例子,一个div从左到右移动一定的距离,分别看看这几种方案的具体实现。如有不妥还望指正。

目标效果

开始:

image.png

结果:

image.png

一、CCS animation

这里省略了html部分,我们直接看css:

.box{
    height: 100px;
    width: 100px;
    animation: move 5s linear;
    position: absolute;
    background: #409EFF;
    left: 200px;
}
@keyframes move {
    0%{
        left: 0;
    }
    100%{
        left: 200px;
    }
}

二、CSS transition

想到这里我们很容易想到这样去写css来实现一个动画,对的,transition使用的一般场景就是有一个如hover的状态时去改变样式。

.box{
    height: 100px;
    width: 100px;
    left: 0;
    position: absolute;
    background: #409EFF;
    transition: 5s linear;
}
.box:hover{
    left: 200px;
}

但是像上面的方式不能实现我们目标需求,所以稍微修改一下:

<style>
    .box{
        height: 100px;
        width: 100px;
        left: 0;
        position: absolute;
        background: #409EFF;
        transition: 5s linear;
    }
    .target{
        left: 200px;
    }
</style>
<script>
    window.onload = ()=>{
        const box = document.getElementsByClassName("box")[0];
        box.className = "target box";
    };
</script>

三、setInterval & setTimeout

这里把单纯使用js定时器的方式归为一类,方式如下:

setInterval(move, 10);
const box = document.getElementsByClassName("box")[0];
let n = 0;
function move() {
    if (n>=200) {
        return
    }
    box.style.left = n + 1 + "px";
    n += 1;
}
const box = document.getElementsByClassName("box")[0];
let n = 0;
function move() {
    if (n>=200) {
        return
    }
    box.style.left = n + 1 + "px";
    n += 1;
    setTimeout(move,10);
}
move();

四、requestAnimationFrame

const box = document.getElementsByClassName("box")[0];
let n = 0;
function move() {
    if (n>=200) {
        return
    }
    box.style.left = n + 1 + "px";
    n += 1;
    requestAnimationFrame(move);
}
move();

五、Canvas

因为canvas只能由js操控绘制,其实这种方法也是js的方式实现动画,只是动起来的不是dom元素,而是画布展示;

<body>
    <canvas id="canvas" ></canvas>
</body>
<script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0,0,300,100);
    ctx.fillStyle = "#409EFF";
    ctx.fillRect(0,0,100,100);
    let n = 0;
    function move() {
        if (n >= 200) {
            return
        }
        ctx.clearRect(0, 0, 300, 100);
        ctx.fillRect(n+1, 0, 100, 100);
        n += 1;
        requestAnimationFrame(move);
    }
    move();
</script>

六、SVG

用svg技术来实现,你会发现代码非常少;

<svg>
    <Rect x="200" y="0" width="100" height="100" fill="#409EFF" >
        <animate attributeName="x" from="0" to="200" dur="5"/>
    </Rect>
</svg>

总结

上面我们只提出了实现方案,没有对比就没有伤害,那么接着我们来横向对比下各种方式方法的优势和缺点,以及适合使用的场景。

方法优势缺点场景
css animation可分关键帧定制动画兼容性稍复杂动画,
css transition写法简单不灵活元素状态改变时的简单动画
setInterval & setTimeout兼容性好卡顿掉帧不支持css3 的场景
requestAnimationFrame灵活使用js兼容性是定时器的优化方案
Canvasdom少,灵活js操控编码相对复杂元素多的复杂动画
SVG代码少不支持形变动画常用于改变位置等自身属性的动画