乘以 css 矩阵导致动画加速
Multiplying css matrices causes animation to accelerate
我有两个 css 3d 矩阵,我在每一帧上乘以它们,将结果存储在一个新数组中并使用该新数组更新我的 [=21] 的 css3 矩阵变换=].它现在终于可以工作了,但不幸的是我遇到了一些意想不到的行为。由于将它们相乘,它实际上在每一帧上都加速了。因此,最后一次矩阵乘积的乘积会再次与另一个矩阵相乘,依此类推。
我该怎么做才能解决这个问题?
https://jsfiddle.net/testopia/qjfz17g3/15/
var elem = document.getElementsByTagName("div")[0];
var inc = 0;
var matrix = [3, 0, 0, 0,
0, 3, 0, 0,
0, 0, 3, 0,
0, 0, 0, 1];
var matrixLength = matrix.length;
var request = null;
var product = [];
function rotateX() {
let deg = inc * (180 / Math.PI);
let cos = Math.cos(inc);
let sin = Math.sin(inc);
let x = [1, 0, 0, 0,
0, cos, -sin, 0,
0, sin, cos, 0,
0, 0, 0, 1];
dot(x, matrix);
applyTransform();
updateMatrix();
product = [];
}
function updateMatrix() {
var str = elem.style.transform,
stripped = str.substring(str.indexOf("(") + 1, str.length - 1);
matrix = stripped.split(", ");
for (let i = 0; i < matrixLength; i++) {
matrix[i] = parseFloat(matrix[i]);
}
}
function applyTransform() {
elem.style.transform = `matrix3d(${product[0]}, ${product[1]}, ${product[2]}, ${product[3]}, ${product[4]}, ${product[5]}, ${product[6]}, ${product[7]}, ${product[8]}, ${product[9]}, ${product[10]}, ${product[11]}, ${product[12]}, ${product[13]}, ${product[14]}, ${product[15]})`;
}
function init() {
rotateX();
inc += 0.01;
requestAnimationFrame(init);
}
init();
function dot(rows, columns) {
product.push((rows[0] * columns[0]) + (rows[1] * columns[4]) + (rows[2] * columns[8]) + (rows[3] * columns[12]))
product.push((rows[0] * columns[1]) + (rows[1] * columns[5]) + (rows[2] * columns[9]) + (rows[3] * columns[13]))
product.push((rows[0] * columns[2]) + (rows[1] * columns[6]) + (rows[2] * columns[10]) + (rows[3] * columns[14]))
product.push((rows[0] * columns[3]) + (rows[1] * columns[7]) + (rows[2] * columns[11]) + (rows[3] * columns[15]))
product.push((rows[4] * columns[0]) + (rows[5] * columns[4]) + (rows[6] * columns[8]) + (rows[7] * columns[12]))
product.push((rows[4] * columns[1]) + (rows[5] * columns[5]) + (rows[6] * columns[9]) + (rows[7] * columns[13]))
product.push((rows[4] * columns[2]) + (rows[5] * columns[6]) + (rows[6] * columns[10]) + (rows[7] * columns[14]))
product.push((rows[4] * columns[3]) + (rows[5] * columns[7]) + (rows[6] * columns[11]) + (rows[7] * columns[15]))
product.push((rows[8] * columns[0]) + (rows[9] * columns[4]) + (rows[10] * columns[8]) + (rows[11] * columns[12]))
product.push((rows[8] * columns[1]) + (rows[9] * columns[5]) + (rows[10] * columns[9]) + (rows[11] * columns[13]))
product.push((rows[8] * columns[2]) + (rows[9] * columns[6]) + (rows[10] * columns[10]) + (rows[11] * columns[14]))
product.push((rows[8] * columns[3]) + (rows[9] * columns[7]) + (rows[10] * columns[11]) + (rows[11] * columns[15]))
product.push((rows[12] * columns[0]) + (rows[13] * columns[4]) + (rows[14] * columns[8]) + (rows[15] * columns[12]))
product.push((rows[12] * columns[1]) + (rows[13] * columns[5]) + (rows[14] * columns[9]) + (rows[15] * columns[13]))
product.push((rows[12] * columns[2]) + (rows[13] * columns[6]) + (rows[14] * columns[10]) + (rows[15] * columns[14]))
product.push((rows[12] * columns[3]) + (rows[13] * columns[7]) + (rows[14] * columns[11]) + (rows[15] * columns[15]))
}
一般来说,您不应使用矩阵来存储对象状态并逐帧相乘,因为您会遇到浮点精度问题,并且您的矩阵可能会在多次乘法后中断。正交轴将不再正交,它们的长度可能会改变。
只需将缩放和旋转存储为浮点数,每帧修改这些浮点数,然后每帧从中构建最终矩阵。
这可能无法解决您的确切问题,但我相信它会在很长一段时间内为您提供帮助 运行。
这是因为每一帧你都在增加 init
函数内的 inc
变量,所以每一帧你都在增加每一帧旋转的旋转量。在每一帧上,您都从 style
属性获取当前矩阵,该属性已经包含之前的旋转,然后您递增 inc
,因此您在矩阵中存储一个增量,并且您还将增量存储在 inc
内,因此您有效地将每帧的增量加倍。
相反,您可以保持 inc
不变,不要增加它,这样就可以了。
例如,这里有一个 JSBin:http://jsbin.com/doyadakado/edit?html,css,js,output
我有两个 css 3d 矩阵,我在每一帧上乘以它们,将结果存储在一个新数组中并使用该新数组更新我的 [=21] 的 css3 矩阵变换=].它现在终于可以工作了,但不幸的是我遇到了一些意想不到的行为。由于将它们相乘,它实际上在每一帧上都加速了。因此,最后一次矩阵乘积的乘积会再次与另一个矩阵相乘,依此类推。
我该怎么做才能解决这个问题?
https://jsfiddle.net/testopia/qjfz17g3/15/
var elem = document.getElementsByTagName("div")[0];
var inc = 0;
var matrix = [3, 0, 0, 0,
0, 3, 0, 0,
0, 0, 3, 0,
0, 0, 0, 1];
var matrixLength = matrix.length;
var request = null;
var product = [];
function rotateX() {
let deg = inc * (180 / Math.PI);
let cos = Math.cos(inc);
let sin = Math.sin(inc);
let x = [1, 0, 0, 0,
0, cos, -sin, 0,
0, sin, cos, 0,
0, 0, 0, 1];
dot(x, matrix);
applyTransform();
updateMatrix();
product = [];
}
function updateMatrix() {
var str = elem.style.transform,
stripped = str.substring(str.indexOf("(") + 1, str.length - 1);
matrix = stripped.split(", ");
for (let i = 0; i < matrixLength; i++) {
matrix[i] = parseFloat(matrix[i]);
}
}
function applyTransform() {
elem.style.transform = `matrix3d(${product[0]}, ${product[1]}, ${product[2]}, ${product[3]}, ${product[4]}, ${product[5]}, ${product[6]}, ${product[7]}, ${product[8]}, ${product[9]}, ${product[10]}, ${product[11]}, ${product[12]}, ${product[13]}, ${product[14]}, ${product[15]})`;
}
function init() {
rotateX();
inc += 0.01;
requestAnimationFrame(init);
}
init();
function dot(rows, columns) {
product.push((rows[0] * columns[0]) + (rows[1] * columns[4]) + (rows[2] * columns[8]) + (rows[3] * columns[12]))
product.push((rows[0] * columns[1]) + (rows[1] * columns[5]) + (rows[2] * columns[9]) + (rows[3] * columns[13]))
product.push((rows[0] * columns[2]) + (rows[1] * columns[6]) + (rows[2] * columns[10]) + (rows[3] * columns[14]))
product.push((rows[0] * columns[3]) + (rows[1] * columns[7]) + (rows[2] * columns[11]) + (rows[3] * columns[15]))
product.push((rows[4] * columns[0]) + (rows[5] * columns[4]) + (rows[6] * columns[8]) + (rows[7] * columns[12]))
product.push((rows[4] * columns[1]) + (rows[5] * columns[5]) + (rows[6] * columns[9]) + (rows[7] * columns[13]))
product.push((rows[4] * columns[2]) + (rows[5] * columns[6]) + (rows[6] * columns[10]) + (rows[7] * columns[14]))
product.push((rows[4] * columns[3]) + (rows[5] * columns[7]) + (rows[6] * columns[11]) + (rows[7] * columns[15]))
product.push((rows[8] * columns[0]) + (rows[9] * columns[4]) + (rows[10] * columns[8]) + (rows[11] * columns[12]))
product.push((rows[8] * columns[1]) + (rows[9] * columns[5]) + (rows[10] * columns[9]) + (rows[11] * columns[13]))
product.push((rows[8] * columns[2]) + (rows[9] * columns[6]) + (rows[10] * columns[10]) + (rows[11] * columns[14]))
product.push((rows[8] * columns[3]) + (rows[9] * columns[7]) + (rows[10] * columns[11]) + (rows[11] * columns[15]))
product.push((rows[12] * columns[0]) + (rows[13] * columns[4]) + (rows[14] * columns[8]) + (rows[15] * columns[12]))
product.push((rows[12] * columns[1]) + (rows[13] * columns[5]) + (rows[14] * columns[9]) + (rows[15] * columns[13]))
product.push((rows[12] * columns[2]) + (rows[13] * columns[6]) + (rows[14] * columns[10]) + (rows[15] * columns[14]))
product.push((rows[12] * columns[3]) + (rows[13] * columns[7]) + (rows[14] * columns[11]) + (rows[15] * columns[15]))
}
一般来说,您不应使用矩阵来存储对象状态并逐帧相乘,因为您会遇到浮点精度问题,并且您的矩阵可能会在多次乘法后中断。正交轴将不再正交,它们的长度可能会改变。
只需将缩放和旋转存储为浮点数,每帧修改这些浮点数,然后每帧从中构建最终矩阵。
这可能无法解决您的确切问题,但我相信它会在很长一段时间内为您提供帮助 运行。
这是因为每一帧你都在增加 init
函数内的 inc
变量,所以每一帧你都在增加每一帧旋转的旋转量。在每一帧上,您都从 style
属性获取当前矩阵,该属性已经包含之前的旋转,然后您递增 inc
,因此您在矩阵中存储一个增量,并且您还将增量存储在 inc
内,因此您有效地将每帧的增量加倍。
相反,您可以保持 inc
不变,不要增加它,这样就可以了。
例如,这里有一个 JSBin:http://jsbin.com/doyadakado/edit?html,css,js,output