原文链接: 使用增量矩阵解决同时修改transform导致的冲突问题
上一篇: 生成指定长度和进制的BigInt
一般做法
类似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的最新状态经过这个增量矩阵变换后的状态
所以可以一边向下走, 一边向右走, 还能同时进行放大, 放大不能进行简单相加
<!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>