SVG linearGradient方向

时间:2016-04-20 16:33:57

标签: svg

我在一个圆圈内有一个简单的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度。至少,这是docs声称的那个。我试图将此rotate设置为更大的数字,但这不会产生预期的结果。

我理解这个问题是linearGradient没有transform来自中心。我想,我必须使用linearGradient的{​​{3}}属性,根本没有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 个答案:

答案 0 :(得分:2)

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

如果您只需要担心圆圈,那么应用轴对齐渐变并旋转圆圈会更简单。

<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>