首页 > 解决方案 > 径向进度条末端的圆边

问题描述

我正在使用 d3.js 创建一个径向进度条,我已经实现了这一点,但我面临的问题是我无法创建每一侧的圆形边缘我附上了输出的图像和预期的变化在输出中也是如此。

下面是我用来创建径向进度条的代码

<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
  .progress {
      display: inline-block;
      padding: 20px;
  }

  .radial-progress { 
    &__text {
      font-family: Arial, sans-serif;
      font-size: 2rem;
      font-weight: bold;
    }  
  }
</style>

<div style="background:#2E98C5" class="background">
<div
  data-text-colour="#2E98C5" //Text color
  class="progress"> 
</div>

</div>
<script>
var renderProgress = function(el,background) {

    //Note: i have kept the track color to be same as the background color so that
    //      it seems that there is no track

  var start = 0;
  //var background='#2E98C5';
  var actual_count=12;
  var total_count=20;
  var end = (actual_count/total_count)*100;
  //var end = el.dataset.progress;
  
  var colours = {
    fill: "white",                          //common for both 
    //track: '#' + el.dataset.trackColour,
    text:  el.dataset.textColour,
    //stroke: '#' + el.dataset.strokeColour,
  }
  
  var radius = 68;
  var border = 8;
  var strokeSpacing = el.dataset.strokeSpacing;
  var endAngle = Math.PI * 2;
  var formatText = d3.format('.0%');
  var boxSize = radius * 2;
  var count = end;
  var progress = start;
  var step = end < start ? -0.01 : 0.01;
  
  //Define the circle
  var circle = d3.arc()
    .startAngle(0)
    .innerRadius(radius)
    .outerRadius(radius - border);
  
  //setup SVG wrapper
  var svg = d3.select(el)
    .append('svg')
    .attr('width', boxSize)
    .attr('height', boxSize);
  
  // ADD Group container
  var g = svg.append('g')
    .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')');
  
  //Setup track
  var track = g.append('g').attr('class', 'radial-progress');
  track.append('path')
    .attr('class', 'radial-progress__background')
    .attr('fill', background)
    .attr('stroke', colours.stroke)
    .attr('stroke-width',  '0px')
    .attr('d', (end/100)*360);
    //.attr('d', circle.endAngle(endAngle));
  
  //Add colour fill
  var value = track.append('path')
    .attr('class', 'radial-progress__value')
    .attr('fill', colours.fill)
    .attr('stroke', colours.stroke)
    .attr('stroke-width', strokeSpacing + 'px');
  
  
  //This circle is just created to give the effect of border over circle  
  var numberText = track.append('circle')
    .attr('fill', "#DBDBDB")        // This colr is constant in bot the control design
    .attr('dy', '.5rem')
    .attr('r', 51);

    //Add circle
  var numberText = track.append('circle')
    .attr('fill', "white")                    //This
    .attr('dy', '.5rem')
    .attr('r', 48);
    
  
  //Add text value
  var numberText = track.append('text')
    .attr('class', 'radial-progress__text')
    .attr('fill', colours.text)
    .text( function (d) {
                
                return actual_count.toString() +"/" +total_count.toString();
            })//Pass the value that should be at the centre
    .attr('font-size', '30px')
    .attr('text-anchor', 'middle')
    .attr('dy', '.5rem');
  
  function update(progress) {
    //update position of endAngle
    value.attr('d', circle.endAngle(-(endAngle * progress)));// -ve so that it goes left to right
    //update text value
    //numberText.text(formatText(progress));
    //numberText.text(actual_count.toString() +"/" +total_count.toString()); //Puts the text in the center
  };
  
  function iterate() {
    //call update to begin animation
    update(progress);
    
    if (count > 0) {
      //reduce count till it reaches 0
      count--;
      //increase progress
      progress += step;
      //Control the speed of the fill
      setTimeout(iterate, 10);
    }
  };
  
  iterate();
}

Array.prototype.slice.call(document.querySelectorAll('.progress')).forEach(el => {
  renderProgress(el,'#2E98C5');
});
</script>

在此处输入图像描述

我从其他来源获取了图像,因为它突出了我想要做的事情。在此先感谢任何帮助或指导都会很棒。

标签: javascripthtmlcssd3.js

解决方案


编辑 1: 根据 adrew Reid 的建议,我能够工作,下面是工作的代码

<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
  .progress {
      display: inline-block;
      padding: 20px;
  }

  .radial-progress { 
    &__text {
      font-family: Arial, sans-serif;
      font-size: 2rem;
      font-weight: bold;
    }  
  }
</style>

<div style="background:#2E98C5" class="background">
<div
  data-text-colour="#2E98C5" //Text color
  class="progress"> 
</div>

</div>
<script>
var renderProgress = function(el,background) {

    //Note: i have kept the track color to be same as the background color so that
    //      it seems that there is no track

  var start = 0;
  //var background='#2E98C5';
  var actual_count=12;
  var total_count=20;
  var end = (actual_count/total_count)*100;
  //var end = el.dataset.progress;
  
  var colours = {
    fill: "white",                          //common for both 
    //track: '#' + el.dataset.trackColour,
    text:  el.dataset.textColour,
    //stroke: '#' + el.dataset.strokeColour,
  }
  
  var radius = 68;
  var border = 8;
  var strokeSpacing = el.dataset.strokeSpacing;
  var endAngle = Math.PI * 2;
  var formatText = d3.format('.0%');
  var boxSize = radius * 2;
  var count = end;
  var progress = start;
  var step = end < start ? -0.01 : 0.01;
  
  //Define the circle
  var circle = d3.arc()
    .startAngle(0)
    .innerRadius(radius)
    .outerRadius(radius - border)
    .cornerRadius(12);
  
  //setup SVG wrapper
  var svg = d3.select(el)
    .append('svg')
    .attr('width', boxSize)
    .attr('height', boxSize);
  
  // ADD Group container
  var g = svg.append('g')
    .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')');
  
  //Setup track
  var track = g.append('g').attr('class', 'radial-progress');
  track.append('path')
    .attr('class', 'radial-progress__background')
    .attr('fill', background)
    .attr('stroke', colours.stroke)
    .attr('stroke-width',  '0px')
    .attr('d', (end/100)*360);
    //.attr('d', circle.endAngle(endAngle));
  
  //Add colour fill
  var value = track.append('path')
    .attr('class', 'radial-progress__value')
    .attr('fill', colours.fill)
    .attr('stroke', colours.stroke)
    .attr('stroke-width', strokeSpacing + 'px');
  
  
  //This circle is just created to give the effect of border over circle  
  var numberText = track.append('circle')
    .attr('fill', "#DBDBDB")        // This colr is constant in bot the control design
    .attr('dy', '.5rem')
    .attr('r', 51);

    //Add circle
  var numberText = track.append('circle')
    .attr('fill', "white")                    //This
    .attr('dy', '.5rem')
    .attr('r', 48);
    
  
  //Add text value
  var numberText = track.append('text')
    .attr('class', 'radial-progress__text')
    .attr('fill', colours.text)
    .text( function (d) {
                
                return actual_count.toString() +"/" +total_count.toString();
            })//Pass the value that should be at the centre
    .attr('font-size', '30px')
    .attr('text-anchor', 'middle')
    .attr('dy', '.5rem');
  
  function update(progress) {
    //update position of endAngle
    value.attr('d', circle.endAngle(-(endAngle * progress)));// -ve so that it goes left to right
    //update text value
    //numberText.text(formatText(progress));
    //numberText.text(actual_count.toString() +"/" +total_count.toString()); //Puts the text in the center
  };
  
  function iterate() {
    //call update to begin animation
    update(progress);
    
    if (count > 0) {
      //reduce count till it reaches 0
      count--;
      //increase progress
      progress += step;
      //Control the speed of the fill
      setTimeout(iterate, 10);
    }
  };
  
  iterate();
}

Array.prototype.slice.call(document.querySelectorAll('.progress')).forEach(el => {
  renderProgress(el,'#2E98C5');
});
</script>

推荐阅读