Reputation: 11
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
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
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:
target
innerHTML
d3.svg.arc
-> d3.arc
Upvotes: 1
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