Scale by corners using mouse

Hi, Am trying to make scale by dragging corners but i can’t get it right as same speed as the mouse speed

The script until now:

//left up

        let IsDown = false;
        let OldX = 0;
        let OldY = 0;
        Dots[0].onmousedown = (e) => {
            IsDown = true;
        };

        Dots[0].onmouseup = (e) => {
            IsDown = false;
        };

        // Dots[0] Corner Lef Up
        Dots[0].onmousemove = (e) => {
            if (!IsDown) return;
            e.preventDefault();
            e.stopPropagation();
            console.log("Scale left up");
            let rect = Canvas.getBoundingClientRect();
            let _mouse = new THREE.Vector2();
            _mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
            _mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
            if (_mouse.x < OldX) {
                sprite.scale.set(
                sprite.scale.x - _mouse.x,
                sprite.scale.y,
                sprite.scale.z
                );
            } else {
                sprite.scale.set(
                sprite.scale.x + _mouse.x,
                sprite.scale.y,
                sprite.scale.z
                );
            }
            OldX = _mouse.x;
            OldY = _mouse.y;
        };

any ideas may helps !

Here is an idea, but it wasn’t easy. And the code is not open source, sorry.

1 Like

nice job bro amazing work

i can scale from corner but still couldn’t find how to make the point follow the mouse exactly
2021-04-05 15-04-49

i think it’s missing unproject.

not a mathematician but that’s worked for me:

const removeZ = new THREE.Vector3(1, 1, 0)
const temp = new THREE.Vector3()
// ...
const unprojectedPoint = temp
  .set((x / size.width) * 2 - 1, -(y / size.height) * 2 + 1, 0)
  .unproject(camera)
  .multiply(removeZ)
  .clone()

x/y is the events clientX/clientY, size is the canvas size in pixels.

1 Like

i apply your lines the scaling became slower and the mouse still no following

image
image

You could try optimizing your code…
For example you are calling getMousePos 4 times in your mouseMove function.
Call it once and assign the value to a vector3D that’s declared once, outside the function.
i.e let currentMousePos = new THREE.Vector3();
And at the start of the move call currentMousePos = getMousePos(e);

You could go deeper, but that’s a start.

That should give you a performance boost :slight_smile:

yes i agree for now all my thinking in scaling problems after that i will improve this script
Thank you

First, your getMousePos function is returning a value in screen space [-1,1]. So the difference between 2 mouse moves will be very small and not related at all to the Object size.

For this kind of transformation I would advise to work in world space : get the actual 3D point. Best practice is to use unproject as proposed by drcmda, since this would make your code independant from the camera.
You can even keep the Z component to ensure your code work with any kind of projection and from any viewing direction.

From there you will get two 3D points corresponding to the mouse move.
Let’s call dX and dY the distance variations in X and Y.
Let’s call Box the current axis aligned bounding box of your object.

Scaling your object in X is adding 2 * dX to the current Object size which is Box.getSize().x.
So the scaling factor to apply to the current object will be something like sX = 1 + 2*dX / Box.getSize().x
But since the object may already be scaled, you need to multiply this with the current scale value, not add it.

Another good practice is to refer to the original position / scale of your object (ie their values on the mouse down event), during all the scaling action. This will prevent small rounding errors to accumulate.

Hope this helps.

2 Likes

Thank you it works, i really appreciate you help :heart: :heart: