【问题标题】:Fix linear gradient of SVG circle修复 SVG 圆的线性渐变
【发布时间】:2020-11-21 18:29:02
【问题描述】:

我有以下圆形进度条。一切都很好,除了渐变。圆实际上是2个弧。当脚本绘制第一条弧线时,渐变为红色->蓝色。所以圆圈的开始是红色的。而且尾巴是蓝色的。但是当第二个弧被绘制时,渐变的开始会变成蓝色,我不知道如何修复它。我不希望它改变颜色。我希望渐变始终相同

function update(percentage) {

  var width = 160,
    height = 160,
    cx = width / 2,
    cy = height / 2,
    start_angle = 0,
    barsize = 10;

  var r = Math.min(cx, cy) - barsize / 2;

  if (percentage === 100) {
    percentage -= 0.0001;
  }

  var end_angle = start_angle + percentage * Math.PI * 2 / 100;

  var x1 = cx + r * Math.sin(start_angle),
    y1 = cy - r * Math.cos(start_angle),
    x2 = cx + r * Math.sin(end_angle),
    y2 = cy - r * Math.cos(end_angle);

  // This is a flag for angles larger than than a half circle
  // It is required by the SVG arc drawing component
  var big = 0;
  if (end_angle - start_angle > Math.PI) big = 1;

  // This string holds the path details
  var d = "M" + x1 + "," + y1 + // Start at (x1,y1)
    " A" + r + "," + r + // Draw an arc of radius r
    " 0 " + big + " 1 " + // Arc details...
    x2 + "," + y2;



  document.getElementById('path').setAttribute('d', d);

}

function animate(start, finish) {
  setTimeout(function() {
    update(start);

    console.log(document.getElementsByClassName('progress__content'))
    let element = document.getElementsByClassName('progress__content')[0];
    element.textContent = start + '%';


    start += 1;
    if (start <= finish) {
      animate(start, finish);
    } else {
      return;
    }
  }, 10);
}


function go() {
  animate(0, 100);
}
.progress {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: 100px;
  width: 200px;
  height: 200px;
}

.progress__content {
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -50px;
  margin-top: -23px;
  font-family: Helvetica;
  font-size: 40px;
  width: 103px;
  height: 47px;
  text-align: center;
}

body {
  background: #f1f1f1;
}
<button onclick="go()">Click me</button>

<div class="progress clip-svg">
  <div class="progress__content">0%</div>
  <svg width="160" height="160">
            <defs>
                <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop stop-color="#EE3028" offset="0" />
                    <stop stop-color="#067BC2" offset="1" />
                </linearGradient>
            </defs>
            
            <ellipse rx="75" ry="75" cx="80" cy="80" stroke="#f2f2f2" fill="none" stroke-width="10"></ellipse>
            <g>
                <path id="path" stroke-width="10" stroke="url(#gradient)" fill="none" d="">
                </path>
            </g>
        </svg>
</div>

【问题讨论】:

    标签: svg linear-gradients


    【解决方案1】:

    渐变会发生变化,因为您在整个路径上定义了渐变,并且随着路径对象向下和向左增长,渐变停止位置也会不断重新定义。解决方案是将您的 gradientUnits 更改为 userSpaceOnUse - 因此渐变是相对于绘图表面/viewBox 相对于对象定义的。下面可能的实现(我不完全确定你的目标是什么配色方案 - 但调整停止位置和颜色,直到你有你想要的)。

    function update(percentage) {
    
      var width = 160,
        height = 160,
        cx = width / 2,
        cy = height / 2,
        start_angle = 0,
        barsize = 10;
    
      var r = Math.min(cx, cy) - barsize / 2;
    
      if (percentage === 100) {
        percentage -= 0.0001;
      }
    
      var end_angle = start_angle + percentage * Math.PI * 2 / 100;
    
      var x1 = cx + r * Math.sin(start_angle),
        y1 = cy - r * Math.cos(start_angle),
        x2 = cx + r * Math.sin(end_angle),
        y2 = cy - r * Math.cos(end_angle);
    
      // This is a flag for angles larger than than a half circle
      // It is required by the SVG arc drawing component
      var big = 0;
      if (end_angle - start_angle > Math.PI) big = 1;
    
      // This string holds the path details
      var d = "M" + x1 + "," + y1 + // Start at (x1,y1)
        " A" + r + "," + r + // Draw an arc of radius r
        " 0 " + big + " 1 " + // Arc details...
        x2 + "," + y2;
    
    
    
      document.getElementById('path').setAttribute('d', d);
    
    }
    
    function animate(start, finish) {
      setTimeout(function() {
        update(start);
    
        console.log(document.getElementsByClassName('progress__content'))
        let element = document.getElementsByClassName('progress__content')[0];
        element.textContent = start + '%';
    
    
        start += 1;
        if (start <= finish) {
          animate(start, finish);
        } else {
          return;
        }
      }, 10);
    }
    
    
    function go() {
      animate(0, 100);
    }
    .progress {
      position: absolute;
      top: 50%;
      left: 50%;
      margin-top: -100px;
      margin-left: 100px;
      width: 200px;
      height: 200px;
    }
    
    .progress__content {
      position: absolute;
      left: 50%;
      top: 50%;
      margin-left: -50px;
      margin-top: -23px;
      font-family: Helvetica;
      font-size: 40px;
      width: 103px;
      height: 47px;
      text-align: center;
    }
    
    body {
      background: #f1f1f1;
    }
    <button onclick="go()">Click me</button>
    
    <div class="progress clip-svg">
      <div class="progress__content">0%</div>
      <svg width="160" height="160">
                <defs>
                    <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="160" y2="0">
                        <stop stop-color="#EE3028" offset="0" />
                        <stop stop-color="#067BC2" offset="160" />
                    </linearGradient>
                </defs>
                
                <ellipse rx="75" ry="75" cx="80" cy="80" stroke="#f2f2f2" fill="none" stroke-width="10"></ellipse>
                <g>
                    <path id="path" stroke-width="10" stroke="url(#gradient)" fill="none" d="">
                    </path>
                </g>
            </svg>
    </div>

    【讨论】:

    • 非常感谢!这正是我需要的。老实说,我不熟悉 SVG。只是快速阅读,没有详细说明
    猜你喜欢
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多