【问题标题】:Circular progress indicator with a color gradient with SVGs?带有 SVG 的颜色渐变的圆形进度指示器?
【发布时间】:2020-04-22 11:28:11
【问题描述】:

我需要制作一个带有颜色渐变的圆形进度指示器。我还需要将进度圈的“末端”四舍五入。这张图片包含了我想要实现的一切:

这段代码很接近,但没有颜色渐变:

https://codepen.io/adsfdsfhdsafkhdsafjkdhafskjds/pen/OJybqza

var control = document.getElementById('control');
var progressValue = document.querySelector('.progress__value');

var RADIUS = 54;
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;

function progress(value) {
  var progress = value / 100;
  var dashoffset = CIRCUMFERENCE * (1 - progress);

  console.log('progress:', value + '%', '|', 'offset:', dashoffset)

  progressValue.style.strokeDashoffset = dashoffset;
}

control.addEventListener('input', function(event) {
  progress(event.target.valueAsNumber);
});

progressValue.style.strokeDasharray = CIRCUMFERENCE;
progress(60);
.demo {
  flex-direction: column;
  display: flex;
  width: 120px;
}

.progress {
  transform: rotate(-90deg);
}

.progress__meter,
.progress__value {
  fill: none;
}

.progress__meter {
  stroke: grey;
}

.progress__value {
  stroke: blue;
  stroke-linecap: round;
}
<div class="demo">
  <svg class="progress" width="120" height="120" viewBox="0 0 120 120">
        <circle class="progress__meter" cx="60" cy="60" r="54" stroke-width="12" />
        <circle class="progress__value" cx="60" cy="60" r="54" stroke-width="12" stroke="url(#gradient)" />
    </svg>
  <input id="control" type="range" value="60" />
</div>

看起来像这样:

我尝试在笔划中添加linear-gradient,但没有效果:

stroke: linear-gradient(red, yellow);

我也试过stroke="url(#linearColors)",但也没有影响。

<div class="demo">  
  <svg class="progress" width="120" height="120" viewBox="0 0 120 120">
    <linearGradient id="linearColors" x1="0" y1="0" x2="1" y2="1">
      <stop offset="5%" stop-color="#01E400"></stop>
      <stop offset="25%" stop-color="#FEFF01"></stop>
      <stop offset="40%" stop-color="#FF7E00"></stop>
      <stop offset="60%" stop-color="#FB0300"></stop>
      <stop offset="80%" stop-color="#9B004A"></stop>
      <stop offset="100%" stop-color="#7D0022"></stop>
    </linearGradient>
    <circle class="progress__meter" cx="60" cy="60" r="54" stroke-width="12" />
    <circle class="progress__value" cx="60" cy="60" r="54" stroke-width="12" stroke="url(#linearColors)" />
  </svg>
  <input id="control" type="range" value="60" />
</div>

https://jsfiddle.net/yzqmvd16/

【问题讨论】:

  • 可能是因为您的笔画网址错误?渐变定义的 id 是“linearColors”,但你的 url 有 #gradient。
  • @MichaelMullany 我试过了并更新了我的问题,但没有改变。
  • SVG 不支持“沿路径的渐变”或“围绕圆的渐变”(有时称为圆锥渐变)。如果你想要那种效果,你需要使用许多小元素来模拟渐变(根据 Robert 的链接)。

标签: svg


【解决方案1】:

您可以使用 100 个圆形,每个圆形具有不同的填充,而不是使用渐变,从而产生渐变的错觉。我使用fill-opacity 属性将元素设置为完全不透明或完全透明。

希望对你有帮助。

const SVG_NS = 'http://www.w3.org/2000/svg';
const CIRCUMFERENCE = base.getTotalLength()
const UNIT = CIRCUMFERENCE / 100;
let circles=[];//the array of circles

//create 100 circles each with a different fill color to create the illusion of a gradient
for(let i = 0; i<100; i++){
  let pos = base.getPointAtLength(i*UNIT);
  let o = {cx:pos.x,cy:pos.y,r:5.5,'fill-opacity':0,fill:`hsl(220,100%,${50 + (100-i)/2}%)`}
  circles.push(drawCircle(o, progress__value));  
}

progress();

control.addEventListener('input', progress);

function progress(){
  let val = control.valueAsNumber;
  for(let i = 0; i<circles.length; i++){
    if(i<=val){
    circles[i].setAttributeNS(null,'fill-opacity',1)    
    }else{
    circles[i].setAttributeNS(null,'fill-opacity',0)
    }
  } 
}

// a function to create a circle
function drawCircle(o, parent) {
  var circle = document.createElementNS(SVG_NS, 'circle');
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      circle.setAttributeNS(null, name, o[name]);
    }
  }
  parent.appendChild(circle);
  return circle;
}
svg{border:solid}

.demo {
  flex-direction: column;
  display: flex;
  width: 120px;
}

.progress__meter{
    fill: none;
}

.progress__meter {
    stroke: grey;
}
<div class="demo">  
    <svg class="progress"  viewBox="-2 -2 124 124">
        <path class="progress__meter" id="base" d="M60,6A54,54 0 0 1 60,114A54,54 0 0 1 60,6z"  stroke-width="12" />
      <g id="progress__value"></g>
    </svg>
    <input id="control" type="range" value="60" />
</div>

【讨论】:

  • 对我来说非常有趣的原创解决方案
【解决方案2】:

您的原始代码几乎可以正常工作。问题是进度圈的笔触颜色被 CSS 中的 stroke: blue; 覆盖。删除它可以根据需要将渐变应用于圆的笔划。

var control = document.getElementById('control');
var progressValue = document.querySelector('.progress__value');

var RADIUS = 54;
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;

function progress(value) {
  var progress = value / 100;
  var dashoffset = CIRCUMFERENCE * (1 - progress);

  // console.log('progress:', value + '%', '|', 'offset:', dashoffset)

  progressValue.style.strokeDashoffset = dashoffset;
}

control.addEventListener('input', function(event) {
  progress(event.target.valueAsNumber);
});

progressValue.style.strokeDasharray = CIRCUMFERENCE;
progress(60);
.demo {
  flex-direction: column;
  display: flex;
  width: 120px;
}

.progress {
  transform: rotate(-90deg);
}

.progress__meter,
.progress__value {
  fill: none;
}

.progress__meter {
  stroke: grey;
}

.progress__value {
  /* stroke: blue; */
  stroke-linecap: round;
}
<div class="demo">
  <svg class="progress" width="120" height="120" viewBox="0 0 120 120">
    <defs>
      <linearGradient id="linearColors" x1="1" y1="0" x2="0" y2="1">
        <stop offset="5%" stop-color="#01E400"></stop>
        <stop offset="25%" stop-color="#FEFF01"></stop>
        <stop offset="40%" stop-color="#FF7E00"></stop>
        <stop offset="60%" stop-color="#FB0300"></stop>
        <stop offset="80%" stop-color="#9B004A"></stop>
        <stop offset="100%" stop-color="#7D0022"></stop>
      </linearGradient>
    </defs>
    <circle class="progress__meter" cx="60" cy="60" r="54" stroke-width="12" />
    <circle class="progress__value" cx="60" cy="60" r="54" stroke-width="12" stroke="url(#linearColors)" />
  </svg>
  <input id="control" type="range" value="60" />
</div>

【讨论】:

    猜你喜欢
    • 2020-06-24
    • 1970-01-01
    • 2015-03-16
    • 2015-09-06
    • 2011-04-23
    • 2018-10-19
    • 2020-08-25
    • 1970-01-01
    • 2015-11-14
    相关资源
    最近更新 更多