SVG线性渐变方向

3

我在一个圆形中使用了简单的 linearGradient

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
  <linearGradient id="ct-svg-gradient" gradientTransform="rotate(65)">
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="yellow" />
  </linearGradient>

  <circle cx="100" cy="100" r="50" fill="url(#ct-svg-gradient)"/>
</svg>

如您所见,我正在尝试将渐变旋转65度。至少,这是文档所声称的。我尝试将此rotate设置为更大的数字,但结果并非预期。
我了解到这个问题的原因在于linearGradient没有将其transform原点设置为中心。我想,我必须使用linearGradientx1、y1、x2、y2属性,而不使用任何gradientTransform。如果是这样,那么如果我只有应该将渐变旋转到的角度,最简单的获取这四个值的方法是什么?
我有兴趣实现这样一个函数,我的输入是动态的。
function convert(angle_in_degrees) { // or radians, I'll take care of conversion

  // the algorithm I'm interested in

  return {
    x1: ...,
    y1: ...,
    x2: ...,
    y2: ...,
  };
}

我非常感谢任何反馈和建议。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
  <linearGradient id="ct-svg-gradient" gradientTransform="rotate(150)">
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="yellow" />
  </linearGradient>
  <circle cx="100" cy="100" r="50" fill="url(#ct-svg-gradient)"/>
</svg>

1个回答

4

这并不是那么简单。为了让你的渐变从边缘填充对象,你需要传入元素并考虑其边界框。

如果你只需要担心圆形,那么应用一个轴对齐的渐变并旋转圆形会更简单。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
  <linearGradient id="ct-svg-gradient">
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="yellow" />
  </linearGradient>
  <circle cx="100" cy="100" r="50" fill="url(#ct-svg-gradient)" transform="rotate(150,100,100)"/>
</svg>

更新

以下是一个简单的JS函数,可以达到您想要的效果。虽然它不总能给出最佳结果,但它应该很容易理解。

function setGradientAngle(elementId, gradientId, angle)
{
  // Convert angle to radians
  angle = angle * Math.PI / 180;
  // Get element bounding box
  var bbox = document.getElementById(elementId).getBBox();
  // Calculate centre of rotation
  var cx = bbox.x + bbox.width/2;
  var cy = bbox.y + bbox.height/2;
  // Minimum radius we need, to guarantee that gradient stretches the full width
  // This calculation could be cleverer. We are just doing worst case here for simplicity.
  var radius = Math.sqrt(bbox.width*bbox.width+bbox.height*bbox.height)/2;
  // Calculate vector from centre to gradient coords
  var rx = Math.cos(angle) * radius;
  var ry = Math.sin(angle) * radius;
  // Update the gradient coords
  var grad = document.getElementById(gradientId);
  grad.setAttribute("gradientUnits", "userSpaceOnUse");
  grad.setAttribute("x1", cx - rx);
  grad.setAttribute("y1", cy + ry);
  grad.setAttribute("x2", cx + rx);
  grad.setAttribute("y2", cy - ry);
}

setGradientAngle("mypath", "ct-svg-gradient", 150);
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
  <linearGradient id="ct-svg-gradient">
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="yellow" />
  </linearGradient>
  <path id="mypath" fill="url(#ct-svg-gradient)" vector-effect="non-scaling-stroke" d="M116.48,288.71a582.68,582.68,0,0,0-69.84-40.32q-36.32-17.74-33.52-58.06a582.72,582.72,0,0,0,0-80.65Q10.32,69.35,46.64,51.61a582.68,582.68,0,0,0,69.84-40.32q33.52-22.58,67,0a582.67,582.67,0,0,0,69.84,40.32q36.32,17.74,33.52,58.06a582.65,582.65,0,0,0,0,80.65q2.79,40.32-33.52,58.06a582.67,582.67,0,0,0-69.84,40.32Q150,311.29,116.48,288.71Z"/>
</svg>


当对象不太规则时,您很难展示一种从边缘到边缘填充对象的方法吗? - Andrei Glingeanu
你打算给渐变旋转添加动画效果吗? - Paul LeBeau
不需要。只是在加载页面之前配置渐变角度。 - Andrei Glingeanu
1
我更新了我的答案,并提供了一个使用JS更新渐变的示例。 - Paul LeBeau
经过长时间的搜索,这是唯一一个也适用于非矩形路径的答案! - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接