使用增量矩阵解决同时修改transform导致的冲突问题

原文链接: 使用增量矩阵解决同时修改transform导致的冲突问题

上一篇: 生成指定长度和进制的BigInt

下一篇: 从react-use 库里面学到的 ref用法

理解CSS3 transform中的Matrix(矩阵)

一般做法
类似animejs等, 直接修改dom的style属性中的 transform 值
对于单独修改的情况下没啥问题, 但是如果同时修改就会导致相互覆盖, 比如在向右移动的过程中, 向下移动或者进行放大操作, 会出现闪烁以及位置错位
本质原因在于修改了transform中的任一属性会将其他属性覆盖
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
        width: 50px;
        height: 50px;
        background: deepskyblue;
      }
    </style>
  </head>
  <body>
    <button onclick="move('x')">moveX</button>
    <button onclick="move('y')">moveY</button>
    <button onclick="scale()">scale</button>
    <br />
    <br />
    <br />
    <div id="box" class="box"></div>
    <script>
      const box = document.getElementById("box");
      const sleep = (n = 16) => new Promise((r) => setTimeout(r, n));
      async function move(direction) {
        console.log('move')
        const x = 100;
        for (let i = 0; i < 100; i++) {
          await sleep();
          const s = direction === "x" ? `translateX(${i}px)` : `translateY(${i}px)`;
          box.style.transform = s;
        }
      }
      async function scale() {
        console.log('scale')
        const scale = 2;
        for (let i = 0; i <= 100; i++) {
          await sleep();
          box.style.transform = `scale(${1 + i / 100})`;
        }
      }
    </script>
  </body>
</html>

增量矩阵
丝滑流畅!
完美的做到了不同状态的叠加
其本质将动画过程拆分为一个个的增量, 每次都实时计算相对于dom的最新状态经过这个增量矩阵变换后的状态
所以可以一边向下走, 一边向右走, 还能同时进行放大, 放大不能进行简单相加
up-356c7f114e8345d4208f6d34a14892b33a8.png
up-69a286049439c4e851115a31d1360a94881.png
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://unpkg.com/rematrix"></script>
    <style>
      .box {
        width: 50px;
        height: 50px;
        background: deepskyblue;
      }
    </style>
  </head>
  <body>
    <button onclick="move('x')">moveX</button>
    <button onclick="move('y')">moveY</button>
    <button onclick="scale()">scale</button>
    <br />
    <br />
    <br />
    <div id="box" class="box"></div>
    <script>
      const box = document.getElementById("box");
      const sleep = (n = 16) => new Promise((r) => setTimeout(r, n));
      async function move(direction) {
        const x = 100;
        for (let i = 0; i < 100; i++) {
          await sleep();
          const oldMtx =
            getComputedStyle(box).transform === "none"
              ? "matrix(1, 0, 0, 1, 0, 0)"
              : getComputedStyle(box).transform;
          const transform = Rematrix.fromString(oldMtx);
          const s =
            direction === "x" ? Rematrix.translateX(1) : Rematrix.translateY(1);
          let product = [transform, s].reduce(Rematrix.multiply);
          box.style.transform = Rematrix.toString(product);
          console.log("product", product);
        }
      }
      async function scale() {
        const scale = 2;
        for (let i = 1; i <= 100; i++) {
          await sleep();
          const oldMtx =
            getComputedStyle(box).transform === "none"
              ? "matrix(1, 0, 0, 1, 0, 0)"
              : getComputedStyle(box).transform;
          const transform = Rematrix.fromString(oldMtx);
          const s = Rematrix.scale(1.01);
          let product = [transform, s].reduce(Rematrix.multiply);
          box.style.transform = Rematrix.toString(product);
        }
      }
    </script>
  </body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值