根据鼠标位置旋转 SVG 渐变
Rotate SVG gradient based on mouse position
我想根据鼠标位置旋转 svg 的渐变。
机制应该如下,其中[0,0]是鼠标在[=31=左上角],[100%,0]应该是鼠标在[=31=右上角=]等
到目前为止,我所知道的是角度随鼠标位置而变化(仅 mouseX),但不是基于我想要的机制:
https://codepen.io/magglomag/pen/YzKYLaa
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>
角度的操作是通过用JS改变gradientTransform
属性中的X
来实现的:
$( '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>' );
});
此外,我想添加一些缓和,这样改变就不那么难了。这是我发现的一个使用缓动的例子。不与梯度角度变化结合,而是与运动结合,但底层代码可能会有所帮助:https://www.kirupa.com/canvas/mouse_follow_ease.htm
非常感谢任何帮助。
您只需要一点数学知识。您需要 SVG 图像的中心点以及鼠标与该点之间的角度:
相对于<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
演示:https://codepen.io/MXXIV/pen/OJLzEOV
相对于window
// 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
您可以按如下方式使用 atan2
来获取以弧度为单位的角度,并通过乘以 180 / Math.PI
:
将其转换为度数
$('body').mousemove(function(e) {
var {
left: offsetX,
top: offsetY
} = $('svg').offset();
centerX = $('svg').width() / 2 + offsetX;
centerY = $('svg').height() / 2 + offsetY;
mouseX = e.pageX - centerX;
mouseY = e.pageY - centerY;
xy = Math.atan2(mouseY, mouseX) * (180 / Math.PI);
$('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>');
});
svg {
width: 150px;
height: 150px;
}
body {
height: 100vw;
width: 100vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg x="0px" y="0px" viewBox="0 0 150 150">
<style>
.st0 { fill:url( #gradient ); }
</style>
<defs>
<linearGradient gradientTransform="rotate( 0, 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>
<path class="st0" d="M149.3,89.5l0.7-24.6l-15.7-0.5c-1-5.4-2.8-10.8-5.3-16l12.4-9.7l-15.4-19.3l-12.4,9.7 c-4.4-3.6-9.3-6.6-14.5-8.8L102.2,5L77.9,0l-3.2,15.3c-5.6,0-11.3,0.8-16.8,2.4L50.4,4L28.5,15.6L36,29.4 c-4.4,3.7-8.2,7.9-11.3,12.6L10,36.2L0.8,59.1l14.7,5.8c-1,5.5-1.2,11.2-0.5,16.8L0,86.5l7.8,23.4l15-4.9c2.9,5,6.5,9.4,10.5,13.2 L25,131.5l21.2,12.9l8.3-13.3c5.3,1.9,10.9,3.1,16.6,3.4l2.3,15.4l24.6-3.6L95.7,131c2.6-1,5.2-2.1,7.8-3.5c2.5-1.4,4.9-2.9,7.2-4.5 l11.8,10.4L139,115l-11.8-10.4c2.8-4.9,4.9-10.2,6.3-15.6L149.3,89.5z M90,102.7c-15.4,8.2-34.7,2.5-43.1-12.8 c-8.3-15.3-2.5-34.4,12.9-42.6c15.4-8.2,34.7-2.5,43,12.8C111.2,75.3,105.4,94.4,90,102.7z"/>
</svg>
我想根据鼠标位置旋转 svg 的渐变。 机制应该如下,其中[0,0]是鼠标在[=31=左上角],[100%,0]应该是鼠标在[=31=右上角=]等
到目前为止,我所知道的是角度随鼠标位置而变化(仅 mouseX),但不是基于我想要的机制: https://codepen.io/magglomag/pen/YzKYLaa
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>
角度的操作是通过用JS改变gradientTransform
属性中的X
来实现的:
$( '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>' );
});
此外,我想添加一些缓和,这样改变就不那么难了。这是我发现的一个使用缓动的例子。不与梯度角度变化结合,而是与运动结合,但底层代码可能会有所帮助:https://www.kirupa.com/canvas/mouse_follow_ease.htm
非常感谢任何帮助。
您只需要一点数学知识。您需要 SVG 图像的中心点以及鼠标与该点之间的角度:
相对于<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
演示:https://codepen.io/MXXIV/pen/OJLzEOV
相对于window
// 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
您可以按如下方式使用 atan2
来获取以弧度为单位的角度,并通过乘以 180 / Math.PI
:
$('body').mousemove(function(e) {
var {
left: offsetX,
top: offsetY
} = $('svg').offset();
centerX = $('svg').width() / 2 + offsetX;
centerY = $('svg').height() / 2 + offsetY;
mouseX = e.pageX - centerX;
mouseY = e.pageY - centerY;
xy = Math.atan2(mouseY, mouseX) * (180 / Math.PI);
$('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>');
});
svg {
width: 150px;
height: 150px;
}
body {
height: 100vw;
width: 100vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg x="0px" y="0px" viewBox="0 0 150 150">
<style>
.st0 { fill:url( #gradient ); }
</style>
<defs>
<linearGradient gradientTransform="rotate( 0, 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>
<path class="st0" d="M149.3,89.5l0.7-24.6l-15.7-0.5c-1-5.4-2.8-10.8-5.3-16l12.4-9.7l-15.4-19.3l-12.4,9.7 c-4.4-3.6-9.3-6.6-14.5-8.8L102.2,5L77.9,0l-3.2,15.3c-5.6,0-11.3,0.8-16.8,2.4L50.4,4L28.5,15.6L36,29.4 c-4.4,3.7-8.2,7.9-11.3,12.6L10,36.2L0.8,59.1l14.7,5.8c-1,5.5-1.2,11.2-0.5,16.8L0,86.5l7.8,23.4l15-4.9c2.9,5,6.5,9.4,10.5,13.2 L25,131.5l21.2,12.9l8.3-13.3c5.3,1.9,10.9,3.1,16.6,3.4l2.3,15.4l24.6-3.6L95.7,131c2.6-1,5.2-2.1,7.8-3.5c2.5-1.4,4.9-2.9,7.2-4.5 l11.8,10.4L139,115l-11.8-10.4c2.8-4.9,4.9-10.2,6.3-15.6L149.3,89.5z M90,102.7c-15.4,8.2-34.7,2.5-43.1-12.8 c-8.3-15.3-2.5-34.4,12.9-42.6c15.4-8.2,34.7-2.5,43,12.8C111.2,75.3,105.4,94.4,90,102.7z"/>
</svg>