字节青训营-实现前端动画

前端动画实现

最近实在太忙了,没有时间写博客,贴一波最近学的动画代码敷衍一下
在这里插入图片描述

演示地址
动画演示

实现下述动画效果:

  • 控制小球匀速移动
  • 控制小球暂停
  • 控制小球动画终止
  • 控制小球动画倒序播放
  • 控制小球速度
<script>
 function animate({
     
     easing,draw,duration}){
    
    //动画函数

  let start = performance.now();

  let speed = 1 //倍速
  
  //动画状态
  let state = 'cancle';
  let condition = 'order'

  //动画播放进度
  let timeFraction = 0
  let pauseTimeFraction = 0;

  
  const run = function(){
    
    

    requestAnimationFrame(function animate(time){
    
    

        if( state === 'pause'){
    
    

            pauseTimeFraction = timeFraction;
            start = performance.now();
            
        }
        else{
    
    
            console.log("开始执行动画了");
            let tmpProgress = ((time - start) / duration) * speed;
            
            if(condition === 'reverse'){
    
    
                tmpProgress = -tmpProgress
            }
            timeFraction = pauseTimeFraction + tmpProgress 

            if(timeFraction > 1) timeFraction = 1;
            if(timeFraction < 0) timeFraction = 0;         

            let progress = easing(timeFraction);

            draw(progress); 
            
            if(state === 'cancle'){
    
    
                return
            }else{
    
    
                if(condition === 'order'){
    
    
                    if(timeFraction < 1){
    
    
                        requestAnimationFrame(animate);
                    }else{
    
    
                        cancle()
                    }
                }else{
    
    
                    if(timeFraction > 0){
    
    
                        requestAnimationFrame(animate);
                    }else{
    
    
                        cancle()
                    }
                }
            }
           
        }
    })

  }
//   run()
  return{
    
    
      play(){
    
    
          console.log("执行动画");
          state = 'run'
          timeFraction = pauseTimeFraction
          start = performance.now();
          run()
      },        
      pause(){
    
    
        console.log("暂停动画");
        state = 'pause'
        start = performance.now();
      },
      cancle(){
    
    
        console.log("终止动画");
        state = 'cancle'
        condition = 'order'
        speed = 1
        timeFraction = 0
        pauseTimeFraction = 0
        start = performance.now();
        run()
      },
      reverse(){
    
    
        console.log("倒序执行动画");
        condition = 'reverse'
        pauseTimeFraction = timeFraction
        start = performance.now();
      },
      playRate(Speed){
    
    
        console.log("切换动画倍速");
        speed = Speed
        start = performance.now();
        pauseTimeFraction = timeFraction
        run()
      }
  }

}
  const ball = document.querySelector('.ball'); //获取球的dom节点
  
  const draw = (progress) => {
    
    //画笔函数 使得球水平匀速运动
    ball.style.transform = `translate(${
      
      progress}px,0)`  //核心代码,控制球的偏移量
  }

  const animation = animate({
    
    
      duration:2000,
      easing(timeFraction){
    
    
        return timeFraction*200;
      },
      draw
  })

  //通过使用闭包的特性控制函数内部变量

  const play = () => {
    
    
      animation.play()
  }
  const pause = () => {
    
    //暂停动画
    animation.pause()
  }
  const cancle = () => {
    
    //暂停动画
    animation.cancle()
  }
  const reverse = () => {
    
    //倒序执行动画
    animation.reverse()
  }
  const playRate = (speed) => {
    
    //切换动画倍速
    animation.playRate(speed)
  }
</script>

完整代码如下
html

完整代码如下

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="container">
        <div class="axisX"></div>
        <div class="axisY"></div>
        <div class="ball"></div>
        <div class="button-container">
          <div class="button" onClick="play()">play</div>
          <div class="button" onClick="pause()">pause</div>
          <div class="button" onClick="cancle()">cancle</div>
          <div class="button" onClick="reverse()">reverse</div>
          <div class="button" onClick="playRate(2)">切换2倍速</div>
        </div>
      </div>
</body>
</html>
function animate({
     
     easing,draw,duration}){
    
    //动画函数

  let start = performance.now();

  let speed = 1 //倍速
  
  //动画状态
  let state = 'cancle';
  let condition = 'order'

  //动画播放进度
  let timeFraction = 0
  let pauseTimeFraction = 0;

  
  const run = function(){
    
    

    requestAnimationFrame(function animate(time){
    
    

        if( state === 'pause'){
    
    

            pauseTimeFraction = timeFraction;
            start = performance.now();
            
        }
        else{
    
    
            console.log("开始执行动画了");
            let tmpProgress = ((time - start) / duration) * speed;
            
            if(condition === 'reverse'){
    
    
                tmpProgress = -tmpProgress
            }
            timeFraction = pauseTimeFraction + tmpProgress 

            if(timeFraction > 1) timeFraction = 1;
            if(timeFraction < 0) timeFraction = 0;         

            let progress = easing(timeFraction);

            draw(progress); 
            
            if(state === 'cancle'){
    
    
                return
            }else{
    
    
                if(condition === 'order'){
    
    
                    if(timeFraction < 1){
    
    
                        requestAnimationFrame(animate);
                    }else{
    
    
                        cancle()
                    }
                }else{
    
    
                    if(timeFraction > 0){
    
    
                        requestAnimationFrame(animate);
                    }else{
    
    
                        cancle()
                    }
                }
            }
           
        }
    })

  }
//   run()
  return{
    
    
      play(){
    
    
          console.log("执行动画");
          state = 'run'
          timeFraction = pauseTimeFraction
          start = performance.now();
          run()
      },        
      pause(){
    
    
        console.log("暂停动画");
        state = 'pause'
        start = performance.now();
      },
      cancle(){
    
    
        console.log("终止动画");
        state = 'cancle'
        condition = 'order'
        speed = 1
        timeFraction = 0
        pauseTimeFraction = 0
        start = performance.now();
        run()
      },
      reverse(){
    
    
        console.log("倒序执行动画");
        condition = 'reverse'
        pauseTimeFraction = timeFraction
        start = performance.now();
        play()
      },
      playRate(Speed){
    
    
        console.log("切换动画倍速");
        speed = Speed
        start = performance.now();
        pauseTimeFraction = timeFraction
        run()
      }
  }

}
  const ball = document.querySelector('.ball'); //获取球的dom节点
  
  const draw = (progress) => {
    
    //画笔函数 使得球水平匀速运动
    ball.style.transform = `translate(${
      
      progress}px,0)`  //核心代码,控制球的偏移量
  }

  const animation = animate({
    
    
      duration:2000,
      easing(timeFraction){
    
    
        return timeFraction*200;
      },
      draw
  })

  //通过使用闭包的特性控制函数内部变量

  const play = () => {
    
    
      animation.play()
  }
  const pause = () => {
    
    //暂停动画
    animation.pause()
  }
  const cancle = () => {
    
    //暂停动画
    animation.cancle()
  }
  const reverse = () => {
    
    //倒序执行动画
    animation.reverse()
  }
  const playRate = (speed) => {
    
    //切换动画倍速
    animation.playRate(speed)
  }
 body {
    
    
  margin: 0;
  padding: 0;
}

#container {
    
    
  position: absolute;
  width: 100%;
  height: 100vh;
}

.axisX {
    
    
  height: 2px;
  background: black;
  width: 100%;
  position: absolute;
  top: 60%;
  transform: translate(0, -1px);
}

.axisY {
    
    
  width: 2px;
  background: black;
  height: 100vh;
  position: absolute;
  left: 50%;
  transform: translate(-1px, 0);
}

.ball {
    
    
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 20px;
  background: red;
  top: calc(60% - 20px);
  left: calc(50% - 20px);
}
   
.ball::before {
    
    
  content: "";
  position: absolute;
  left: 10px;
  top: 10px;
  background: yellow;
  width: 10px;
  height: 10px;
  border-radius: 5px;
}

.button-container {
    
    
  position: absolute;
  bottom: 50px;
  left: 100px;
}

.button {
    
    
  cursor: pointer;
  border: 2px solid black;
  padding: 10px 20px;
  font-size: 20px;
  display: inline-block;
}
.button:hover {
    
    
  background: gray;
}

猜你喜欢

转载自blog.csdn.net/Laollaoaolao/article/details/122628086