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. 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. 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.
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.
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. 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.
Hopefully someone can help, thank you very much