У меня есть простой класс преобразования для применения переводов, масштабов и поворотов в div в любом произвольном порядке:
class TransformDiv{
constructor(div)
{
this.div = div;
this.translateX = 0;
this.translateY = 0;
this.scaleX = 1;
this.scaleY = 1;
this.shearX = 0;
this.shearY = 0;
}
translate(x, y)
{
this.translateX += x;
this.translateY += y;
this.setTransform();
}
scale(x, y, anchorX = 0, anchorY = 0)
{
this.scaleX *= x;
this.shearX *= x;
this.scaleY *= y;
this.shearY *= y;
this.translateX -= (this.translateX - anchorX) * (1 - x);
this.translateY -= (this.translateY - anchorY) * (1 - y);
this.setTransform();
}
rotate(rad, anchorX = 0, anchorY = 0)
{
let cos = Math.cos(rad);
let sin = Math.sin(rad);
// the composition of two successive rotations are additive
let newScaleX = this.scaleX * cos + this.shearX * sin;
let newShearX = this.scaleX * (-sin) + this.shearX * cos;
let newShearY = this.shearY * cos + this.scaleY * sin;
let newScaleY = this.shearY * (-sin) + this.scaleY * cos;
this.scaleX = newScaleX;
this.shearX = newShearX;
this.shearY = newShearY;
this.scaleY = newScaleY;
//rotation about an arbitrary point
let originX = (this.translateX - anchorX);
let originY = (this.translateY - anchorY);
this.translateX -= (originY * sin - originX * (cos - 1));
this.translateY -= (-originY * (cos - 1) - originX * sin);
this.setTransform();
}
setTransform()
{
this.div.style.transform = `matrix(${this.scaleX}, ${this.shearY}, ${this.shearX}, ${this.scaleY}, ${this.translateX}, ${this.translateY})`;
}
}
Проблема возникает, когда я хочу повернуть изображение после того, как был получен неоднородный масштаб.
Изменить - новый интерактивный пример: https://codepen.io/manstie/pen/RwGGOmB
Вот созданный мной пример: https://jsfiddle.net/ft61q230/1/
В этом примере:
div2.translate(100, 100);
div2.scale(2, 1, 100, 100);
div2.rotate(Math.PI / 2, 100, 100);
Ожидаемый результат - Test 1 Text
и Test 2 Text
будут иметь одинаковую длину, как если бы вы поворачивались от верхнего левого угла div по часовой стрелке на 90 градусов; но, как вы можете видеть, результат таков, что логика вращения, которую я выполняю, сохраняет масштаб на оси мирового пространства, так что теперь Test 2 Text
в два раза выше, чем в два раза длиннее.
Текущий результат:
Желаемый результат:
Текущая логика вращения основана на умножении существующей матрицы преобразования, которая составляет поворот, на другую матрицу преобразования, содержащую угол для поворота, но я понимаю, что это не так просто, и мне не хватает чего-то, чтобы сохранить локально-осевой масштаб.
Спасибо за помощь.
Редактировать:
Был рекомендован DOMMatrix
, который выполняет всю эту математику для меня, но имеет ту же проблему, хотя есть некоторый перекос, который я не считаю точным:
https://jsfiddle.net/heqo7vrt/1/
Перекос вызван функцией масштабирования, которая масштабирует его локальную ось X при повороте, а затем вращается после того, как масштабирование этой локальной оси X не сохраняется. Кроме того, функция DOMMatrix
translate имеет переводы, применяемые к ее локальной оси, что нежелательно в моей ситуации, но если бы ее функция поворота работала должным образом, я мог бы ее использовать.