JavaScript 练手小技巧:动画本质和应用

一、JS动画本质

JavaScript 的动画,本质来说,就是让标签动起来。而想要让标签动起来,其本质就是改变标签属性,比如高宽,左边距,上边距,透明度等。

JavaScript 动画的本质就是间隔极短的时间(毫秒),持续改变标签的某个属性

一般用用定时器,就能得到动画效果。

定时器,可以选择 setInterval, setTimeout,以及 requestAnimationFrame。

以控制 div.box 的移动为例子。

  • setInterval
let aniFun= function(){
    
    
    // 动画代码
};
let myset = setInterval(aniFun,30);
let box = document.getElementById("box");
let dis = 0;
let speed = 10 ;
let aniFun= function(){
    
    
    // 动画代码
    dis += speed;
    box.style.transform=`translateX(${
      
      dis}px)`;
};
let myset2 = setInterval(aniFun,30);
  • setTimeout
let aniFun= function(){
    
    
    // 动画代码
    myset2 = setTimeout(aniFun,30);
};
let myset2 = setTimeout(aniFun,30);
let box = document.getElementById("box");
let dis = 0;
let speed = 10 ;
let aniFun= function(){
    
    
    // 动画代码
    dis += speed;
    box.style.transform=`translateX(${
      
      dis}px)`;
    myset2 = setTimeout(aniFun,30);
};
let myset2 = setTimeout(aniFun,30);
  • requestAnimationFrame

使用方法跟 setTimeout 很类似。需要在动画函数的最后,再次回调它自己。

let aniFun= function(){
    
    
    // 动画代码
    req = requestAnimationFrame(aniFun);
};
let req = requestAnimationFrame(aniFun);
let box = document.getElementById("box");
let dis = 0;
let speed = 10 ;
let aniFun= function(){
    
    
    // 动画代码
    dis += speed;
    box.style.transform=`translateX(${
      
      dis}px)`;
    req = requestAnimationFrame(aniFun);
};
let req = requestAnimationFrame(aniFun);

更推荐使用 requestAnimationFrame

  1. requestAnimationFrame 是由系统来决定回调函数的执行时机。如果屏幕刷新率是 60Hz,那么回调函数就每16.7ms (1000/60)被执行一次。如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。
  2. 当页面失去焦点(切换到另外一个页面),requestAnimationFrame 的动画会暂停,以解决系统资源。

二、利用事件触发动画

点击按钮让 div.box 动起来。

<div id="box" class="box"></div>
<button id="btn">点击开始运动</button>

1. 基本操作

let btn = document.getElementById("btn");
let box = document.getElementById("box");

let aniFun ;
let dis = 0;
let speed = 30;
let req ;
let BoxGo = function(){
    
    
    dis += speed ;
    box.style.transform=`translateX(${
      
      dis}px)`;
    req = requestAnimationFrame(BoxGo);
};

btn.addEventListener("click",function () {
    
    
    BoxGo();
});

上述代码有两个问题:

  1. 如果连续点击按钮,box 会不停持续加速运动。

    解决方法:点击按钮后,先停止之前的动画,再开始新的动画。

  2. box 会不停的向右运动,不会停止下来。

解决方法如下。

2. 设定动画距离

超过了距离就停止动画。

let btn = document.getElementById("btn");
let box = document.getElementById("box");

let aniFun ;
let dis = 0;
let speed = 30 ;
let target = 500 ;
let BoxGo = function(){
    
    
    dis += speed ;
    // 限制运动距离
    if( dis >= target){
    
    
        dis = target ;
        cancelAnimationFrame(aniFun);
    }else{
    
    
        console.info(dis);
        box.style.transform=`translateX(${
      
      dis}px)`;
        aniFun = requestAnimationFrame(BoxGo);
    }
};

btn.addEventListener("click",function () {
    
    
    // 防止重复叠加动画:开始新的动画前,取消之前的动画。
    cancelAnimationFrame(aniFun);
    BoxGo();
});

3. 设定动画时间

设定动画的时间,超过了时间就停止动画。

let btn = document.getElementById("btn");
let box = document.getElementById("box");

let aniFun ;
let dis = 0;
let speed = 30;
let startTime = 0;
let aniTime = 500 ;  // 动画时间为500毫秒。
let BoxGo = function(){
    
    
    let time = new Date();
    let p = time - startTime ;
    dis += speed ;
    // 限制运动时间 。到了 0.5s 就停止
    console.info( p );
    if( p >= aniTime ){
    
    
        cancelAnimationFrame(aniFun);
    }else{
    
    
        box.style.transform=`translateX(${
      
      dis}px)`;
        aniFun = requestAnimationFrame(BoxGo);
    }
};

btn.addEventListener("click",function () {
    
    
    // 防止重复叠加动画:开始新的动画前,取消之前的动画。
    cancelAnimationFrame(aniFun);
    startTime = new Date();
    BoxGo();
});

4. 设定动画时间和动画距离

let btn = document.getElementById("btn");
let box = document.getElementById("box");

let aniFun ;
let speed = 30;
let aniTime = 500 ; // 运动时间 500 毫秒
let aniDis = 1500 ;  // 运动距离 500px
let startTime = 0;
let BoxGo = function(){
    
    
    let time = new Date();
    let pastTime = time - startTime ; // 已经运动的时间点
    console.info(pastTime);
    let past = Math.min(pastTime/aniTime,1)  ;  // 0-1
    // 限制运动时间 。到了 0.5s 就停止
    if( pastTime >= aniTime ){
    
    
        pastTime = 500 ;
        cancelAnimationFrame(aniFun);
    }else{
    
    
        box.style.transform=`translateX(${
      
      past*aniDis}px)`;
        aniFun = requestAnimationFrame(BoxGo);
    }
};

btn.addEventListener("click",function () {
    
    
    // 防止重复叠加动画:开始新的动画前,取消之前的动画。
    cancelAnimationFrame(aniFun);
    startTime = new Date();
    BoxGo();
});

三、应用

图片的淡入淡出。

<img src="images/pic1.jpg" alt="" id="pic">
let pic = document.getElementById("pic");
let aniTime = 500;  // 动画时间
let startTime = new Date();
let aniFun = function(){
    
    
    let pastTime = new Date() - startTime ;
    let past = Math.min( pastTime / aniTime ,1 ) ;
    pic.style.opacity = past ;
    if( past >= 1){
    
    
        cancelAnimationFrame(req);
    }else{
    
    
        req = requestAnimationFrame(aniFun);
    }
};
let req = requestAnimationFrame(aniFun);

封装成函数:

let fadeAni = function({
    
    duration=500,
                        targetV=1,
                        startV=0,
                        element
                       }={
    
    }){
    
    
    let aniTime = duration;  // 动画时间
    let startTime = new Date();
    let aniFun = function(){
    
    
        let pastTime = new Date() - startTime ;
        let past = Math.min( pastTime / aniTime ,1 ) ;
        element.style.opacity = (targetV- startV)* past + startV ;
        if( past >= 1){
    
    
            cancelAnimationFrame(req);
        }else{
    
    
            req = requestAnimationFrame(aniFun);
        }
    };
    let req = requestAnimationFrame(aniFun);
};
let pic = document.getElementById("pic");
// 淡入
fadeAni({
    
    
    duration:1000,
    startV:0,
    targetV:1,
    element:pic
});
let pic = document.getElementById("pic");
// 淡出
fadeAni({
    
    
    duration:1000,
    startV:1,
    targetV:0,
    element:pic
});

猜你喜欢

转载自blog.csdn.net/weixin_42703239/article/details/111413252