Steve
Steve

Reputation: 11

3 progress bar in one html file using js

How to display 3 progress bar that have different data using js and html. First of all, sorry for my poor English, I hope you will understand me after all I want 3 same circle to show 3 different data. When I add 3 of the same js codes in which I change the "radialprogress" ID, I always see one progress bar. I have this code

Html:

<div class="row">
    <div>
        <div class="radialprogress" id="radialprogress1"></div>
    </div>
    <div>
        <div class="radialprogress" id="radialprogress2"></div>
    </div>
    <div>
        <div class="radialprogress" id="radialprogress3"></div>
    </div> </div>

JS code which I also put in html:

    <script>
    var svg ;

function drawProgress(end){ 
d3.select("svg").remove() 
  if(svg){
  svg.selectAll("*").remove();
  
}
var wrapper = document.getElementById('radialprogress1');
var start = 0;
 
var colours = {
  fill: '#12ea8d',
  track: '#555555',
  text: '#00C0FF',
  stroke: '#172b4d',
}

var radius = 80;
var border = 12;
var strokeSpacing = 4;
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.svg.arc()
  .startAngle(0)
  .innerRadius(radius)
  .outerRadius(radius - border);

//setup SVG wrapper
svg = d3.select(wrapper)
  .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('fill', colours.track)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px')
  .attr('d', circle.endAngle(endAngle));

//Add colour fill
var value = track.append('path')
  .attr('fill', colours.fill)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px');

//Add text value
var numberText = track.append('text')
  .attr('fill', colours.text)
  .attr('text-anchor', 'middle')
  .attr('dy', '.5rem'); 

  //update position of endAngle
  value.attr('d', circle.endAngle(endAngle * end));
  //update text value
  numberText.text(formatText(end));
  
}

$('#submitClick').click(function(){
  var val = parseInt($('{$statwi}').val());
   drawProgress({$statwi}/100)
})
 
drawProgress({$statwi}/100)
</script>
<script>
    var svg ;

function drawProgress(end){ 
d3.select("svg").remove() 
  if(svg){
  svg.selectAll("*").remove();
  
}
var wrapper = document.getElementById('radialprogress2');
var start = 0;
 
var colours = {
  fill: '#12ea8d',
  track: '#555555',
  text: '#00C0FF',
  stroke: '#172b4d',
}

var radius = 80;
var border = 12;
var strokeSpacing = 4;
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.svg.arc()
  .startAngle(0)
  .innerRadius(radius)
  .outerRadius(radius - border);

//setup SVG wrapper
svg = d3.select(wrapper)
  .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('fill', colours.track)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px')
  .attr('d', circle.endAngle(endAngle));

//Add colour fill
var value = track.append('path')
  .attr('fill', colours.fill)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px');

//Add text value
var numberText = track.append('text')
  .attr('fill', colours.text)
  .attr('text-anchor', 'middle')
  .attr('dy', '.5rem'); 

  //update position of endAngle
  value.attr('d', circle.endAngle(endAngle * end));
  //update text value
  numberText.text(formatText(end));
  
}

 
drawProgress(1/100)
</script>
<script>
    var svg ;

function drawProgress(end){ 
d3.select("svg").remove() 
  if(svg){
  svg.selectAll("*").remove();
  
}
var wrapper = document.getElementById('radialprogress3');
var start = 0;
 
var colours = {
  fill: '#12ea8d',
  track: '#555555',
  text: '#00C0FF',
  stroke: '#172b4d',
}

var radius = 80;
var border = 12;
var strokeSpacing = 4;
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.svg.arc()
  .startAngle(0)
  .innerRadius(radius)
  .outerRadius(radius - border);

//setup SVG wrapper
svg = d3.select(wrapper)
  .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('fill', colours.track)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px')
  .attr('d', circle.endAngle(endAngle));

//Add colour fill
var value = track.append('path')
  .attr('fill', colours.fill)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px');

//Add text value
var numberText = track.append('text')
  .attr('fill', colours.text)
  .attr('text-anchor', 'middle')
  .attr('dy', '.5rem'); 

  //update position of endAngle
  value.attr('d', circle.endAngle(endAngle * end));
  //update text value
  numberText.text(formatText(end));
  
}

 
drawProgress(3/100)
</script>

Thank You

Upvotes: 1

Views: 202

Answers (3)

herrstrietzel
herrstrietzel

Reputation: 17155

You could use a data-attribute to store percentage data for each gauge instance:

  <div class="radialprogress" data-progress="3 / 100"></div>

Your drawing function drawProgressGauges() would search/query for all <div> with a class of "radialprogress".
So you don't need to run/call it for every new gauge element added to your HTML.
Unique IDs are also added automatically.

// draw gauges if present 
drawProgressGauges();

function drawProgressGauges() {
  let gauges = document.querySelectorAll(".radialprogress");
  if (gauges.length) {
    gauges.forEach(function (el, i) {
      // set auto ids
      let autoID = 'progress'+i;
      el.id = autoID;
      // get percentages by data attribute
      let endAtt = el.getAttribute('data-progress').split('/');
      end = endAtt[0] / endAtt[1];
      var colours = {
        fill: "#12ea8d",
        track: "#555555",
        text: "#00C0FF",
        stroke: "#172b4d"
      };

      var radius = 80;
      var border = 12;
      var strokeSpacing = 4;
      var endAngle = Math.PI * 2;
      var formatText = d3.format(".0%");
      var boxSize = radius * 2 + (border/2);

      //Define the circle
      var circle = d3
        .arc()
        .startAngle(0)
        .innerRadius(radius)
        .outerRadius(radius - border );

      //setup SVG wrapper
      let 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("fill", colours.track)
        .attr("stroke", colours.stroke)
        .attr("stroke-width", strokeSpacing + "px")
        .attr("d", circle.endAngle(endAngle));

      //Add colour fill
      var value = track
        .append("path")
        .attr("fill", colours.fill)
        .attr("stroke", colours.stroke)
        .attr("stroke-width", strokeSpacing + "px");

      //Add text value
      var numberText = track
        .append("text")
        .attr("fill", colours.text)
        .attr("text-anchor", "middle")
        .attr("dy", ".5rem");

      //update position of endAngle
      value.attr("d", circle.endAngle(endAngle * end));
      //update text value
      numberText.text(formatText(end));
    });
  }
}
.row{
  display:flex;
  width:100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div class="row">
  <div class="radialprogress" data-progress="3 / 100"></div>
  <div class="radialprogress" data-progress="15 / 100"></div>
  <div class="radialprogress" data-progress="33 / 100"></div>
  <div class="radialprogress" data-progress="80 / 100"></div>
</div>

If you're interested in a static approach, using only svg:
Pie chart using circle element

Upvotes: 0

Shameen
Shameen

Reputation: 3258

You could modify the function to accept the target element as a parameter:

function drawProgress(end, target) {
  var svg;
  var wrapper = document.getElementById(target);
  wrapper.innerHTML = "";
  var start = 0;

  var colours = {
    fill: '#12ea8d',
    track: '#555555',
    text: '#00C0FF',
    stroke: '#172b4d',
  }

  var radius = 80;
  var border = 12;
  var strokeSpacing = 4;
  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
  svg = d3.select(wrapper)
    .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('fill', colours.track)
    .attr('stroke', colours.stroke)
    .attr('stroke-width', strokeSpacing + 'px')
    .attr('d', circle.endAngle(endAngle));

  //Add colour fill
  var value = track.append('path')
    .attr('fill', colours.fill)
    .attr('stroke', colours.stroke)
    .attr('stroke-width', strokeSpacing + 'px');

  //Add text value
  var numberText = track.append('text')
    .attr('fill', colours.text)
    .attr('text-anchor', 'middle')
    .attr('dy', '.5rem');

  //update position of endAngle
  value.attr('d', circle.endAngle(endAngle * end));
  //update text value
  numberText.text(formatText(end));
}
drawProgress(3 / 100, 'radialprogress1');
drawProgress(15 / 100, 'radialprogress2');
drawProgress(80 / 100, 'radialprogress3');
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div class="row">
  <div>
    <div class="radialprogress" id="radialprogress1"></div>
  </div>
  <div>
    <div class="radialprogress" id="radialprogress2"></div>
  </div>
  <div>
    <div class="radialprogress" id="radialprogress3"></div>
  </div>
</div>

I made these changes to the code, to help explain it:

  1. added param/args target
  2. at the bottom, replaced the code to call the function with a simpler example
  3. the variable 'svg' is now only inside the function
  4. for removing the previous SVG i swapped it from removing All to removing just the target's innerHTML
  5. renamed one broken function call d3.svg.arc -> d3.arc

Upvotes: 1

nare214
nare214

Reputation: 327

First, never use one ID for multiple elements. Use different IDs, so for example:

<div class="row">
    <div>
        <div style="width: 160px;float: left;margin-right: 0px;" id="radialprogress1"></div>
    </div>
    <div>
        <div style="width: 160px;float: left;margin-right: 0px;" id="radialprogress2"></div>
    </div>
    <div>
        <div style="width: 160px;float: left;margin-right: 0px;" id="radialprogress3"></div>
    </div>
</div>

Then, you have to adjust your JavaScript code, too.

In Addition, I have a tip: Use classes and CSS to style multiple elements at once:

<div class="row">
    <div>
        <div class="radialprogress" id="radialprogress1"></div>
    </div>
    <div>
        <div class="radialprogress" id="radialprogress2"></div>
    </div>
    <div>
        <div class="radialprogress" id="radialprogress3"></div>
    </div>
</div>
<style>
    .radialprogress {
        width: 160px;
        float: left;
        margin-right: 0px;
    }
</style>

If you want to learn CSS, visit W3Wchools.

Upvotes: 1

Related Questions