Масштабирование повернутого прямоугольника и поиск новых контрольных точек и центра

1

Этот код в ссылке на код, который я собираюсь поделиться, немного сложный и плотный, поэтому я на самом деле прошу не использовать код, а совет.

https://codepen.io/anon/pen/LLEedg?editors=0010

Речь идет о масштабировании поворотного прямоугольника и поиске новых масштабированных координат вершин прямоугольника.

Когда я поворачиваю прямоугольник, я переводю его центр на 0,0 окна просмотра и выполняю поворот. Затем я переводил его на прежнее место. Оно работает.

Затем я делаю масштаб, перемещая начало transform-origin в нижний правый прямоугольник. Чтобы избежать прыжка, я компенсирую сумму шкалы, а также перевод, действие которого было применено к моим контрольным точкам. В конце, когда я перемещаю начало transform origin в повернутое нижнее левое прямоугольник, я не вижу прыжка. Я вычисляю новый ограничивающий прямоугольник с новыми точками управления (не повернутые координаты, а масштабированные версии).

После этого я делаю масштаб с новым transform-origin с тем же методом. На этот раз я возьму новую масштабированную, но не повернутую новую ограничительную рамку и сделаю поворот таким же способом, чтобы найти новые масштабированные и повернутые координаты контрольной точки.

Я ожидаю, что они будут точно в вершинах изображений, но они немного ушли.

Вероятно, это касается масштабирования от начала вращения точки управления и неправильной компенсации.

Чтобы воспроизвести проблему в ссылке с кодом, которую я разделяю.

Сначала поверните произвольное количество влево.

Затем нарисуйте верхнюю левую ручку влево.

Маленькие черные точки должны приземляться точно в центре зеленых ручек.

Маленькие черные точки - это новые координаты контрольных точек, которые я вычисляю. Красный поглаженный прямоугольник - это новый ограничивающий прямоугольник, который поворачивается на 0,0 и переводится обратно, чтобы вычислить новые контрольные точки. Синяя мишень с красным заполнением является источником transform-origin изображения. Желтая мишень с зеленым заполнением - это transform-origin ручек, которые я не намеренно обновляю, чтобы не запутаться. Голубой круг заполнения с большим радиусом с непрозрачностью - это новый расчетный центр из маленьких черных точек.

Теги:
svg
matrix
css-transforms

1 ответ

0
Лучший ответ

Я решил эту проблему, как показано ниже, я бы хотел услышать лучшее решение.

Это охватывает поиск новых вершин и центра после операций поворота и масштабирования.

Все приведенные ниже кодовые блоки должны оцениваться после каждого события масштаба и события поворота.

Вероятно, это будет событие перетаскивания для дескриптора.

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;



 }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню