js实现曲线运动

2022-07-15 12:26:15

编译器:vscode

目的:为了实现商品到购物车的曲线运动,而模拟的一次小红点曲线运动

准备工作:实现小红点的曲线,需要一个公式(数学的曲线公式,物理的匀变速公式,贝塞尔曲线公式),我这儿使用的是贝塞尔曲线公式。

贝塞尔曲线算法可参考网址:贝塞尔曲线

代码

小红点运动

      function init(i) {
        let t = 0;
        const p1 = [0, 0];
        const cp = [600, 700];
        const p2 = [1200, 0];
        let redDot = document.createElement("div");
        //为了对小红点实现模糊化,带有后缀,不要模糊化可自行更改类名
        redDot.classList.add(`dot${i}`);
        document.body.appendChild(redDot);
        move();
        function move() {
          if(t > 1) {
            document.body.removeChild(redDot);
            return;
          }
          requestAnimationFrame(()=>{
            let [newx, newy] = towBezier(t, p1, cp, p2);
            redDot.style.left = newx + "px";
            redDot.style.top = newy + "px";
            t += 0.001;
            move();
          });
        }
      }
/*
*  t为百分比,可以当作变量来实现小红点的运动
*  p1为起点坐标
*  p2为终点坐标
*  cp为控制点坐标
*/
//二阶贝塞尔曲线,返回当前百分比所运动到的坐标点
      function towBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
      }

小红点模糊化

用类名不同实现透明度不同,来实现模糊化有后缀的感觉

//生成多个相同但出发时刻不同的点,目的为了生成残影
      function manyDot() {
        let i = 0;
        let myadd = setInterval(() => {
          if( i == 5) {
            clearInterval(myadd);
            return;
          }
          init(i);
          i++;
        }, 20);
      }

css片段

      * {
        padding: 0;
        margin: 0;
      }
      .dot0 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
      }
      .dot1 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.5;
      }
      .dot2 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.4;
      }
      .dot3 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.3;
      }
      .dot4 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.2;
      }

完整代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>小球抛物线</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .dot0 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
      }
      .dot1 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.5;
      }
      .dot2 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.4;
      }
      .dot3 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.3;
      }
      .dot4 {
        width: 10px;
        height: 10px;
        background-color: red;
        border-radius: 50%;
        position: fixed;
        opacity: 0.2;
      }
    </style>
  </head>
  <body>
    <script>
      function init(i) {
        let t = 0;
        const p1 = [0, 0];
        const cp = [600, 700];
        const p2 = [1200, 0];
        let redDot = document.createElement("div");
        redDot.classList.add(`dot${i}`);
        document.body.appendChild(redDot);
        move();
        function move() {
          if(t > 1) {
            document.body.removeChild(redDot);
            return;
          }
          requestAnimationFrame(()=>{
            let [newx, newy] = towBezier(t, p1, cp, p2);
            redDot.style.left = newx + "px";
            redDot.style.top = newy + "px";
            t += 0.001;
            move();
          });
        }
      }
      /*
      * 二阶贝塞尔曲线
      * t为当前百分比,根据t的变化曲线开始变化
      * p1为起点坐标
      * p2为终点坐标
      * cp为控制点
      */
      function towBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
      }
      //生成多个相同但出发时刻不同的点,目的为了生成残影
      function manyDot() {
        let i = 0;
        let myadd = setInterval(() => {
          if( i == 5) {
            clearInterval(myadd);
            return;
          }
          init(i);
          i++;
        }, 20);
      }
      manyDot();
    </script>
  </body>
</html>
  • 作者:ZzDIY
  • 原文链接:https://blog.csdn.net/qq_43526925/article/details/117849515
    更新时间:2022-07-15 12:26:15