Javascript 基于鼠标位置旋转SVG梯度

Javascript 基于鼠标位置旋转SVG梯度,javascript,jquery,svg,gradient,mouse-position,Javascript,Jquery,Svg,Gradient,Mouse Position,我想根据鼠标位置旋转svg的渐变。 该机制应如下所示,其中[0,0]是鼠标位于窗口的左上角,[100%,0]是鼠标位于窗口的右上角等 到目前为止,我只知道鼠标位置上的角度变化mouseX,而不是基于我想要的机制: svg渐变的定义如下: <defs> <linearGradient gradientTransform="rotate( X, 0.5, 0.5 )" id="gradient" gradientUnits="objectBoundingBox">

我想根据鼠标位置旋转svg的渐变。 该机制应如下所示,其中[0,0]是鼠标位于窗口的左上角,[100%,0]是鼠标位于窗口的右上角等

到目前为止,我只知道鼠标位置上的角度变化mouseX,而不是基于我想要的机制:

svg渐变的定义如下:

<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>
此外,我想增加一点放松,这样改变就不那么难了。下面是我发现的一个使用easing的示例。不是与渐变角度更改结合使用,而是与移动结合使用,但底层代码可能会有所帮助:


非常感谢您的帮助。

您所需要的只是一点数学知识。您需要SVG图像的中心点,然后是鼠标与该点之间的角度:

相对于 演示:

相对于窗口
演示:

您所需要的只是一点数学知识。您需要SVG图像的中心点,然后是鼠标与该点之间的角度:

相对于 演示:

相对于窗口 演示:

您可以使用atan2获得以弧度为单位的角度,并通过乘以180/Math.PI将其转换为度:

$'body'.mouseMoveFunction{ 变量{ 左:offsetX, 顶部:越位 }=$'svg'。偏移量; centerX=$'svg'。宽度/2+偏移量; centerY=$'svg'。高度/2+偏移量; mouseX=e.pageX-centerX; mouseY=e.pageY-centerY; xy=Math.atan2mouseY,mouseX*180/Math.PI; $'svg defs'.html; }; svg{ 宽度:150px; 高度:150像素; } 身体{ 高度:100vw; 宽度:100vw; } .st0{fill:url梯度;} 您可以使用atan2获得以弧度为单位的角度,并通过乘以180/Math.PI将其转换为度:

$'body'.mouseMoveFunction{ 变量{ 左:offsetX, 顶部:越位 }=$'svg'。偏移量; centerX=$'svg'。宽度/2+偏移量; centerY=$'svg'。高度/2+偏移量; mouseX=e.pageX-centerX; mouseY=e.pageY-centerY; xy=Math.atan2mouseY,mouseX*180/Math.PI; $'svg defs'.html; }; svg{ 宽度:150px; 高度:150像素; } 身体{ 高度:100vw; 宽度:100vw; } .st0{fill:url梯度;}
你能创建一个互动的例子吗?SVG当然不会太大,以至于不适合这个问题或JSFIDLE。嗨@TomášZato,Codepen上已经有了一个SVG:您能创建一个交互式示例吗?SVG当然不会太大,以至于不适合这个问题或JSFIDLE。嗨@TomášZato,Codepen上已经有一个了:非常感谢!我刚刚意识到我对鼠标的位置有点不精确。在您的解决方案中,渐变直接反应到鼠标与齿轮的角度,这也是一个很好的机制,但我指的是鼠标相对于整个视口的位置。因此,当鼠标位于左上角时,渐变角度为45度,视口右上角为135度,右下角为225度,左下角为315度。非常感谢!我刚刚意识到我对鼠标的位置有点不精确。在您的解决方案中,渐变直接反应到鼠标与齿轮的角度,这也是一个很好的机制,但我指的是鼠标相对于整个视口的位置。因此,当鼠标位于左上角时,渐变角度为45度,视口右上角为135度,右下角为225度,左下角为315度。非常感谢!我刚刚意识到我对鼠标的位置有点不精确。在您的解决方案中,渐变直接反应到鼠标与齿轮的角度,这也是一个很好的机制,但我指的是鼠标相对于整个视口的位置。因此,当鼠标位于左上角时,渐变角度为45度,在视口的右上角为135度,右下角为225度,左下角为315度。好的,您只需设置midx=window.innerWidth/2Nah。根本不需要rect,这是从svg中心的角度。仔细想想,窗口的左侧是x=0,右侧是x=window.innerWidth,所以中间是window.innerWidth/2。高度相同。@shrys检查更新的示例以查看它是否有效。请注意,需要的是innerWidth,而不是outer。否则它在iframes之类的软件中就不起作用了。@user1706680我只需要将我的答案中的代码提取到某个函数中,然后从你链接的文章中复制的代码中调用它。试着玩弄它,如果它不起作用,你可以问另一个问题,也许有人,也许我,会帮你解决它。但我认为你能做到。非常感谢!我刚刚意识到我对鼠标的位置有点不精确。在你的解决方案中,梯度直接反应到鼠标与齿轮的角度,这也是一个很好的机制,但我指的是鼠标
相对于整个视口的位置。因此,当鼠标位于左上角时,渐变角度为45度,在视口的右上角为135度,右下角为225度,左下角为315度。好的,您只需设置midx=window.innerWidth/2Nah。根本不需要rect,这是从svg中心的角度。仔细想想,窗口的左侧是x=0,右侧是x=window.innerWidth,所以中间是window.innerWidth/2。高度相同。@shrys检查更新的示例以查看它是否有效。请注意,需要的是innerWidth,而不是outer。否则它在iframes之类的软件中就不起作用了。@user1706680我只需要将我的答案中的代码提取到某个函数中,然后从你链接的文章中复制的代码中调用它。试着玩弄它,如果它不起作用,你可以问另一个问题,也许有人,也许我,会帮你解决它。但我认为你能做到。
$( '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>' );

});
  // 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
  // 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