Этот код в ссылке на код, который я собираюсь поделиться, немного сложный и плотный, поэтому я на самом деле прошу не использовать код, а совет.
https://codepen.io/anon/pen/LLEedg?editors=0010
Речь идет о масштабировании поворотного прямоугольника и поиске новых масштабированных координат вершин прямоугольника.
Когда я поворачиваю прямоугольник, я переводю его центр на 0,0 окна просмотра и выполняю поворот. Затем я переводил его на прежнее место. Оно работает.
Затем я делаю масштаб, перемещая начало transform-origin
в нижний правый прямоугольник. Чтобы избежать прыжка, я компенсирую сумму шкалы, а также перевод, действие которого было применено к моим контрольным точкам. В конце, когда я перемещаю начало transform origin
в повернутое нижнее левое прямоугольник, я не вижу прыжка. Я вычисляю новый ограничивающий прямоугольник с новыми точками управления (не повернутые координаты, а масштабированные версии).
После этого я делаю масштаб с новым transform-origin
с тем же методом. На этот раз я возьму новую масштабированную, но не повернутую новую ограничительную рамку и сделаю поворот таким же способом, чтобы найти новые масштабированные и повернутые координаты контрольной точки.
Я ожидаю, что они будут точно в вершинах изображений, но они немного ушли.
Вероятно, это касается масштабирования от начала вращения точки управления и неправильной компенсации.
Чтобы воспроизвести проблему в ссылке с кодом, которую я разделяю.
Сначала поверните произвольное количество влево.
Затем нарисуйте верхнюю левую ручку влево.
Маленькие черные точки должны приземляться точно в центре зеленых ручек.
Маленькие черные точки - это новые координаты контрольных точек, которые я вычисляю. Красный поглаженный прямоугольник - это новый ограничивающий прямоугольник, который поворачивается на 0,0 и переводится обратно, чтобы вычислить новые контрольные точки. Синяя мишень с красным заполнением является источником transform-origin
изображения. Желтая мишень с зеленым заполнением - это transform-origin
ручек, которые я не намеренно обновляю, чтобы не запутаться. Голубой круг заполнения с большим радиусом с непрозрачностью - это новый расчетный центр из маленьких черных точек.
Я решил эту проблему, как показано ниже, я бы хотел услышать лучшее решение.
Это охватывает поиск новых вершин и центра после операций поворота и масштабирования.
Все приведенные ниже кодовые блоки должны оцениваться после каждого события масштаба и события поворота.
Вероятно, это будет событие перетаскивания для дескриптора.
heightOfRectangle
и WidthOfRectangle
должны быть масштабированными значениями.
Ex. если у вас текущий масштаб 1,3, то heightOfRectangle
должен быть вашей initial rectangle height*1.3
rotationAngle
должно быть суммой всех углов поворота, применяемых ранее в радианах.
alpha
- это Math.atan2(heightOfRectangle,WidthOfRectangle)
;
r
- Math.sqrt(Math.pow(WidthOfRectangle,2)+Math.pow(heightOfRectangle,2))/2
другими словами гипотенус, разделяемый двумя правыми треугольниками, который делает прямоугольник;
Предполагая, что вы преодолели проблемы происхождения трансформации и можете масштабировать прямоугольник из разных ручек, предотвращая скачки начала трансформации, активным дескриптором является ручка, которую вы перетаскиваете, а противоположная сторона находится там, где находится трансформация. Например, если вы перетаскиваете верхний левый дескриптор, то начало координат должно располагаться в нижней правой части рукоятки.
activeHandle
- это ручка, которую вы перетаскиваете.
tl
для topleft, o
для происхождения br
для прямой и т.д.
tc
означает верхний центр для моего кода, где я перетаскиваю его для вращения.
Это просто означает поворот от события происхождения.
значения, которые начинаются со old
должны быть вашими последними местоположениями ручки перед этим вращением. значения, которые начинаются с new
будут вашими новыми дескрипторами после этого поворота.
rx
является сокращением для повернутого x ry
является аббревиатурой для повернутого y
Вы все еще можете просмотреть ручку здесь, с решенной проблемой.
https://codepen.io/anon/pen/LLEedg?editors=0010
Вы можете просмотреть функцию updateControlPoints
в строке 251.
var cosRot = Math.cos(rotationAngle);
var sinRot = Math.sin(rotationAngle);
if (activeHandle === 'tc') {
var cosAMinusRot = Math.cos(alpha - rotationAngle);
var sinAMinusRot = Math.sin(alpha - rotationAngle);
var cosAPlusRot = Math.cos(alpha + rotationAngle);
var sinAPlusRot = Math.sin(alpha + rotationAngle);
var cos90APlusRot = Math.cos(Math.PI / 2 - alpha + rotationAngle);
var sin90APlusRot = Math.sin(Math.PI / 2 - alpha + rotationAngle);
var ox = old_ox; //means current ox
var oy = old_oy; //means current oy
//tl
var new_x = -r * cosAPlusRot + ox
var new_y = -r * sinAPlusRot + oy
new_tl.rx = new_x;
new_tl.ry = new_y;
//tr
new_x = +r * sin90APlusRot + ox
new_y = -r * cos90APlusRot + oy
new_tr.rx = new_x;
new_tr.ry = new_y;
//bl
new_x = -r * cosAMinusRot + ox
new_y = +r * sinAMinusRot + oy
new_bl.rx = new_x;
new_bl.ry = new_y;
//br
new_x = +r * cosAPlusRot + ox
new_y = +r * sinAPlusRot + oy
new_br.rx = new_x;
new_br.ry = new_y;
}
else if (activeHandle === 'tl') {
var cosAPlusRot = Math.cos(alpha + rotationAngle);
var sinAPlusRot = Math.sin(alpha + rotationAngle);
new_tl.rx = old_br.rx - 2 * r * cosAPlusRot;
new_tl.ry = old_br.ry - 2 * r * sinAPlusRot;
new_bl.rx = old_br.rx - WidthOfRectangle * cosRot;
new_bl.ry = old_br.ry - WidthOfRectangle * sinRot;
new_tr.rx = old_br.rx + HeightOfRectangle * sinRot;
new_tr.ry = old_br.ry - HeightOfRectangle * cosRot;
new_ox = old_br.rx - r * cosAPlusRot;
new_oy = old_br.ry - r * sinAPlusRot;
} else if (activeHandle === 'tr') {
var cos180APlusRot = Math.cos(Math.PI - alpha + rotationAngle);
var sin180APlusRot = Math.sin(Math.PI - alpha + rotationAngle);
new_tl.rx = old_bl.rx + HeightOfRectangle * sinRot;
new_tl.ry = old_bl.ry - HeightOfRectangle * cosRot;
new_br.rx = old_bl.rx + WidthOfRectangle * cosRot;
new_br.ry = old_bl.ry + WidthOfRectangle * sinRot;
new_tr.rx = old_bl.rx - 2 * r * cos180APlusRot;
new_tr.ry = old_bl.ry - 2 * r * sin180APlusRot;
new_ox = old_bl.rx - r * cos180APlusRot;
new_oy = old_bl.ry - r * sin180APlusRot;
} else if (activeHandle === 'bl') {
var cosAPlus90MinusRot = Math.cos(alpha + Math.PI / 2 - rotationAngle);
var sinAPlus90MinusRot = Math.sin(alpha + Math.PI / 2 - rotationAngle);
new_bl.rx = old_tr.rx - 2 * r * sinAPlus90MinusRot;
new_bl.ry = old_tr.ry - 2 * r * cosAPlus90MinusRot;
new_br.rx = old_tr.rx - HeightOfRectangle * sinRot;
new_br.ry = old_tr.ry + HeightOfRectangle * cosRot;
new_tl.rx = old_tr.rx - WidthOfRectangle * cosRot;
new_tl.ry = old_tr.ry - WidthOfRectangle * sinRot;
new_ox = old_tr.rx - r * sinAPlus90MinusRot;
new_oy = old_tr.ry - r * cosAPlus90MinusRot;
} else if (activeHandle === 'br') {
var cosAPlusRot = Math.cos(alpha + rotationAngle);
var sinAPlusRot = Math.sin(alpha + rotationAngle);
new_bl.rx = old_tl.rx - HeightOfRectangle * sinRot;
new_bl.ry = old_tl.ry + HeightOfRectangle * cosRot;
new_br.rx = old_tl.rx + 2 * r * cosAPlusRot;
new_br.ry = old_tl.ry + 2 * r * sinAPlusRot;
new_tr.rx = old_tl.rx + WidthOfRectangle * cosRot;
new_tr.ry = old_tl.ry + WidthOfRectangle * sinRot;
new_ox = old_tl.rx + r * cosAPlusRot;
new_oy = old_tl.ry + r * sinAPlusRot;
}