I've created a custom cursor and I want to change its scale dynamically on fast movements. It's a cursor like this one: Cuberto.com
My cursor: CodeSandBox
When the cursor moves quickly to the right or left, scaleX should grow and get smaller again. When the cursor moves up or down, scaleY should grow and so on...
Edit: New challenge - Get rotation in
Thanks to Terry, who achieved this goal! But now we have a new challenge. If we move the cursor diagonally, the cursor still has to rotate to get a perfect result.
I would divide the velocity by '2'. If we now move the cursor diagonally, we can see that rotation is missing to achieve the desired effect.
Does anyone have an idea?
const scaleX = 1 + velocityX / 2;
const scaleY = 1 + velocityY / 2;
In order to create this effect, here are some steps to achieve that, starting from the end:
scaleX() and scaleY() in CSS transformsMouseEvent object)With this strategy in mind, here is how it could be done:
data object to cache the previous XY coordinates and timestampThis can be done by simply updating the data object:
data() {
return {
hideCursor: false,
prevX: 0,
prevY: 0,
prevTimeStamp: 0,
};
},
mousemove callback:We need to store these values at the very end of the mousemove callback, and place the rest of our logic before that (we will get to that later).
document.addEventListener("mousemove", (e) => {
// SOME LOGIC HERE
// Update cached values
this.prevX = e.pageX;
this.prevY = e.pageY;
this.prevTimeStamp = e.timeStamp;
});
To calculate velocity in the X and Y axes, you need to calculate the absolute difference between previous and current X/Y values, and divide them by the time elapsed:
const deltaX = Math.abs(e.pageX - this.prevX);
const deltaY = Math.abs(e.pageY - this.prevY);
const deltaTime = e.timeStamp - this.prevTimeStamp;
const velocityX = deltaX / deltaTime;
const velocityY = deltaY / deltaTime;
This is completely arbitrarily determined and it's up to you. For me, dividing the calculated velocity by 10 gives an effect that I find not too jarring/abrupt and still perceptible to the user. This value might need to be changed based on the absolute pixel size of the cursor.
const scaleX = 1 + velocityX / 10;
const scaleY = 1 + velocityY / 10;
cursor.style.top = `${e.pageY}px`;
cursor.style.left = `${e.pageX}px`;
cursor.style.transform = `translate(-50%, -50%) scaleX(${scaleX}) scaleY(${scaleY})`;
mouseout event on the viewportThis is so that the cursor is not stuck in a strange state when mouse leaves the viewport:
document.addEventListener('mouseout', () => {
cursor.style.transform = 'none';
});
See an updated example based on your CodeSandbox: