I’d like to rotate the gradient of an svg based on the mouse position. The mechanic should be as followed, where [0,0] is the mouse being in the upper left corder of the window, [100%,0] should be the mouse in the upper right corner of the window etc.
What I have so far is that the angle changes on mouse position (only mouseX) but not based on my desired mechanic: https://codepen.io/magglomag/pen/YzKYLaa
The svg gradient is defined like this:
<defs>
<linearGradient gradientTransform="rotate( X, 0.5, 0.5 )" id="gradient" gradientUnits="objectBoundingBox">
<stop offset="0.4" style="stop-color:#33FF8F"/>
<stop offset="0.6" style="stop-color:#5A33FF"/>
</linearGradient>
</defs>
The manipulation of the angle is realized by changing the X
in the gradientTransform
attribute with JS:
$( 'body' ).mousemove( function( e ) {
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;
xy = mouseX;
$( 'svg defs' ).html( '<linearGradient gradientTransform="rotate(' + xy + ', 0.5, 0.5 )" id="gradient" gradientUnits="objectBoundingBox"><stop offset="0.4" stop-color="#33FF8F"/><stop offset="0.6" stop-color="#5A33FF"/></linearGradient>' );
});
Besides I’d like to add a bit of easing so the change is not that hard. Here’s an example I found which uses easing. Not in combination with a gradient angle change but with a movement but perhaps the underlying code might be helpful: https://www.kirupa.com/canvas/mouse_follow_ease.htm
Any help is much appreciated.
All you need is a bit of math. You need center point of the SVG image and then angle between the mouse and that point:
<svg>
// position of mouse
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;
// client rect of the gear
const svgRoot = document.querySelector("#mysvg");
const rect = svgRoot.getBoundingClientRect();
// center point is x+width/2 and y+height/2
const midx = rect.left + (rect.right - rect.left)/2;
const midy = rect.top + (rect.bottom - rect.top)/2;
// angle
const angle = Math.atan2(midy - mouseY, midx - mouseX);
// The transform uses degrees (0-365), not radians (0 - 2PI)
const angleDeg = angle* 180 / Math.PI
Demo: https://codepen.io/MXXIV/pen/OJLzEOV
// position of mouse
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;
// center point is x+width/2 and y+height/2
const midx = window.innerWidth/2;
const midy = window.innerHeight/2;
// angle
const angle = Math.atan2(midy - mouseY, midx - mouseX);
const angleDeg = angle* 180 / Math.PI