简体   繁体   English

Svg缩放在鼠标拖动时旋转元素

[英]Svg scaling rotated elements on mouse drag

I'm playing around with svgs and matrixes for a project I'd like to work on and I'm trying to implement a free transform with vanilla javascript. 我正在使用svgs和matrixes来处理我想要处理的项目,并且我正在尝试使用vanilla javascript实现自由变换。 As of now I am able to do all transformations with javascript and this library https://www.npmjs.com/package/transformation-matrix#transform ,to help me dealing with matrixes. 到目前为止,我能够使用javascript和这个库进行所有转换https://www.npmjs.com/package/transformation-matrix#transform ,以帮助我处理矩阵。 My code for now is only working with rect elements, but I assume most of the code did will be of use for other elements with some changes. 我现在的代码只适用于rect元素,但我认为大部分代码都会用于其他元素并进行一些更改。

The problem arise when I try to scale a rotated rect. 当我尝试缩放旋转的矩形时出现问题。 In my code, when I click on an element I give it a path around the element, some circles that represent the direction you can scale the rect, 1 for the center and 1 for the rotation. 在我的代码中,当我点击一个元素时,我给它一个围绕元素的路径,一些圆圈代表你可以缩放矩形的方向,1代表中心,1代表旋转。

As I've said I don't have any problem with whatever transformation, be it to translate a rotated/scaled shape or anything else, the only thing i can't figure out how to do is how to scale a rotated shape keeping it's rotation. 正如我所说的那样,对于任何转换都没有任何问题,无论是转换旋转/缩放的形状还是其他任何东西,我唯一无法弄清楚如何做的是如何缩放旋转的形状保持它的回转。

If a rect has 0 rotation, depending on which direction i decide to scale i just do a mix of translate and scale after i get the new width/height based on mouse pointer. 如果一个矩形有0旋转,取决于我决定缩放的方向我只是在我获得基于鼠标指针的新宽度/高度后进行平移和缩放的混合。 This works great and as intended. 这很有效并且符合预期。 If a rect has rotation this breaks and i tought maybe using the euclidean distance between the point from which i scale and the mouse pointer would work but it doesn't. 如果一个矩形有旋转,这会打破,我应该使用我缩放的点和鼠标指针可以工作的点之间的欧氏距离,但事实并非如此。 so i am kinda lost on this. 所以我有点迷失在这上面。

        const elem = document.getElementById('rect2');
        const x = elem.x.baseVal.value;
        const y = elem.y.baseVal.value;
        const width = elem.width.baseVal.value;
        const height = elem.height.baseVal.value;

        // this is a function that return the mouse coords on the canvas- 
        // svg
        const m = this.getCanvasMousePos(e);

        if(type === 'bottom-center'){
            const newH = (m.y - y) / height;
            const s = scale(1,newH);
            const form = toSVG(s);
            elem.setAttribute('transform', form);
        }else if (type === 'top-center'){
            const newH = (y+height - m.y) / height;
            const s = scale(1,newH);
            const t = translate(0,m.y-y)
            const comp = compose(t,s);
            const form = toSVG(comp);
            elem.setAttribute('transform', form);
        }else if (type === 'middle-left') {
            const newW = (x+width - m.x) / width;
            const s = scale(newW,1);
            const t = translate(m.x-x, 0);
            const comp = compose(t,s)
            const form = toSVG(comp);
            elem.setAttribute('transform', form);
        }else if (type === 'middle-right') {
            const newW = (m.x - x) / width;
            const s = scale(newW,1);
            const form = toSVG(s);
            elem.setAttribute('transform', form);
        }else if (type === 'bottom-right') {
            const newW = (m.x - x) / width;
            const newH = (m.y - y) / height;
            const s = scale(newW,newH);
            const form = toSVG(s);
            elem.setAttribute('transform', form);
        }else if (type === 'bottom-left'){
            const newW = ((x + width) - m.x) / width;
            const newH = (m.y - y) / height;
            const t = translate(m.x - x,0);
            const s = scale(newW,newH);
            const comp = compose(t,s)
            const form = toSVG(comp);
            elem.setAttribute('transform', form);
        }else if (type === 'top-left') {
            const newW = ((x + width) - m.x) / width;
            const newH = ((y + height) - m.y) / height;
            const t = translate(m.x-x,m.y-y);
            const s = scale(newW,newH);
            const comp = compose(t,s)
            const form = toSVG(comp);
            elem.setAttribute('transform', form);
        }else if (type === 'top-right') {
            const newW = (m.x - x) / width;
            const newH = ((y + height) - m.y) / height;
            const t = translate(0,m.y-y);
            const s = scale(newW,newH);
            const comp = compose(t,s)
            const form = toSVG(comp);
            elem.setAttribute('transform', form);
        };

This is the code for the non-rotated svgs. 这是非旋转svgs的代码。

Hopefully someone can help, thank you very much 希望有人能提供帮助,非常感谢你

I have found a solution. 我找到了解决方案。

Whenever a shape is rotated you should translate your mouse pointer and the shape as if they are not rotated, do your scaling normally then translating back and rotating at the end. 每当旋转一个形状时,您应该将鼠标指针和形状转换为不旋转,正常缩放然后平移并在结束时旋转。 My problem was that i was trying to rotate before translating back! 我的问题是我在翻译之前试图旋转!

If you use this method the order should be transform(rotate translate scale) because the last one you put is the first to happen! 如果你使用这种方法,顺序应该是变换(旋转平移比例),因为你放的最后一个是第一个发生!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM