I find this code for progress bar circle, But this code just creates one progress bar circle.
I need to create more one progress bar.
This code:
http://jsfiddle.net/Aapn8/3410/
<div class="chart" id="graph" data-percent="88"></div>
JS
var el = document.getElementById('graph'); // get canvas
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
Thank you.
You have already done the hard-work. wrap your code in a function which accepts a DOM element and create circle based on it.
var elems = document.querySelectorAll('.chart'); // get canvas
elems.forEach(function(el) {
createCircle(el);
})
function createCircle(el) {
//Logic to create circle
}
var elems = document.querySelectorAll('.chart'); // get canvas
elems.forEach(function(el) {
createCircle(el);
})
function createCircle(el) {
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
}
div {
position: relative;
margin: 80px;
width: 220px;
height: 220px;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
span {
color: #555;
display: block;
line-height: 220px;
text-align: center;
width: 220px;
font-family: sans-serif;
font-size: 40px;
font-weight: 100;
margin-left: 5px;
}
input {
width: 200px;
}
span {}
<div class="chart" data-percent="88"></div>
<div class="chart" data-percent="32"></div>
Update Fiddle
Related
The following code is generating a circle bar by using canvas. Everything works fine.
But when I tried to change the code so that the percent circle and value view
dont rotate/circulate around until they reach the real position/value I run into
problems. The graph should only view the percentage position within the circle
and the value in the mittle of the circle without rotating/couting up to the real end value.
I know I have to change/delete some things in the JS arcMove() function like
deegres += 1 which is responsible for the rotation steps and so on, but if I tried it didnt work like it should.
window.onload = function() {
var can = document.getElementById('canvas'),
spanProcent = document.getElementById('procent'),
c = can.getContext('2d');
var posX = can.width / 2,
posY = can.height / 2,
fps = 1000 / 200,
procent = 0,
oneProcent = 360 / 100,
result = oneProcent * 64;
c.lineCap = 'round';
arcMove();
function arcMove(){
var deegres = 0;
var acrInterval = setInterval (function() {
deegres += 1;
c.clearRect( 0, 0, can.width, can.height );
procent = deegres / oneProcent;
spanProcent.innerHTML = procent.toFixed();
c.beginPath();
c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + 360) );
c.strokeStyle = '#b1b1b1';
c.lineWidth = '10';
c.stroke();
c.beginPath();
c.strokeStyle = '#3949AB';
c.lineWidth = '10';
c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + deegres) );
c.stroke();
if( deegres >= result ) clearInterval(acrInterval);
}, fps);
}
}
:root {
background: #fff;
}
span#procent {
display: block;
position: absolute;
left: 50%;
top: 50%;
font-size: 50px;
transform: translate(-50%, -50%);
color: #3949AB;
}
span#procent::after {
content: '%';
}
.canvas-wrap {
position: relative;
width: 300px;
height: 300px;
}
<div class="canvas-wrap">
<canvas id="canvas" width="300" height="300"></canvas>
<span id="procent"></span>
</div>
In the arcMove function you have to set degree to result so the interval is done on first call. But if you do not want an animation than you should use a pure css way of displaying it. Checkout the following answer: https://stackoverflow.com/a/41147560/8820118
window.onload = function() {
var can = document.getElementById('canvas'),
spanProcent = document.getElementById('procent'),
c = can.getContext('2d');
var posX = can.width / 2,
posY = can.height / 2,
fps = 1000 / 200,
procent = 0,
oneProcent = 360 / 100,
result = oneProcent * 64;
c.lineCap = 'round';
arcMove();
function arcMove(){
var deegres = result; // change degrees to result, than you won't have the animation.
var acrInterval = setInterval (function() {
deegres += 1;
c.clearRect( 0, 0, can.width, can.height );
procent = deegres / oneProcent;
spanProcent.innerHTML = procent.toFixed();
c.beginPath();
c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + 360) );
c.strokeStyle = '#b1b1b1';
c.lineWidth = '10';
c.stroke();
c.beginPath();
c.strokeStyle = '#3949AB';
c.lineWidth = '10';
c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + deegres) );
c.stroke();
if( deegres >= result ) clearInterval(acrInterval);
}, fps);
}
}
:root {
background: #fff;
}
span#procent {
display: block;
position: absolute;
left: 50%;
top: 50%;
font-size: 50px;
transform: translate(-50%, -50%);
color: #3949AB;
}
span#procent::after {
content: '%';
}
.canvas-wrap {
position: relative;
width: 300px;
height: 300px;
}
<div class="canvas-wrap">
<canvas id="canvas" width="300" height="300"></canvas>
<span id="procent"></span>
</div>
i want to create a curved text in qml it's possible? Is there a javascript library that i can import to do it?
My idea is that it's possible maybe with canvas element but i don't know how i can do it... it's a good idea??
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
//how i can create curved text???
}
}
}
Hello I tried the code into the link posted by #folibis , work perfectly!!!
This is the code :
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
property string nameFont: webFont.name
function drawTextAlongArc(context, str, centerX, centerY, radius, angle)
{
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, -1 * radius);
var char1 = str[n];
context.fillText(char1, 0, 0);
context.restore();
}
context.restore();
}
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 1, 1, 1);
ctx.fillRect(0, 0, width, height);
ctx.font='50px Verdana'
//ctx.font = '30px Courier New'
ctx.textAlign = "center";
var centerX = width / 2;
var centerY = height/2; //height - 30;
var angle = Math.PI * 0.8; // radians
var radius = 180;
ctx.fillStyle="#000000"
drawTextAlongArc(ctx, "Hello World", centerX, centerY, radius, angle);
}
}
}
I'm using PHP to create a foreach loop for stats using HTML5 Canvas. Now everything is working great except the JavaSscript I found to create the Canvas Graph, it gets an element by id and so only manually targets one item, not sure how I can change up this code to target any amount of items created by the PhP foreach loop.
Here is the JavaScript I found along with the HTML element (ignore the PhP variables in the data-attributes, they are returning data):
var el = document.getElementById('graph'); // get canvas
//var el = document.getElementsByClassName("chart");
var options = {
percent: el.getAttribute('data-percent') || 25,
color: el.getAttribute('data-color') || 0,
size: el.getAttribute('data-size') || 90,
lineWidth: el.getAttribute('data-line') || 3,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#eeeeee', 1, 100 / 100);
drawCircle(options.color, options.lineWidth, options.percent / 100);
<div class="chart" id="graph" data-percent="<?php echo $percentage; ?>" data-color="<?php echo $color; ?>" style="color: <?php echo $color; ?>;"></div>
using get element by class name returns an error: Uncaught TypeError: el.getAttribute is not a function
Ok, so getElementsByClassName returns a NodeList object. What you need to do is turn it into an array and loop over all it's elements and execute your code for each of them. Here is a minimally-changed version of how your code should work:
// Get all the elements with 'chart' class as a NodeList object
var elements = document.getElementsByClassName("chart");
// Turn the NodeList into an array
elements = Array.prototype.slice.call(elements);
// Loop over all the elements
elements.forEach(function (el) {
var options = {
percent: el.getAttribute('data-percent') || 25,
color: el.getAttribute('data-color') || 0,
size: el.getAttribute('data-size') || 90,
lineWidth: el.getAttribute('data-line') || 3,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#eeeeee', 1, 100 / 100);
drawCircle(options.color, options.lineWidth, options.percent / 100);
});
<div class="chart" data-percent="100" data-color="red" style="color: red;"></div>
<div class="chart" data-percent="30" data-color="red" style="color: red;"></div>
However, this code should definitely be refactored. For instance, there is no point in declaring drawCircle function on every iteration.
Also read up on getElementByClassName, and forEach.
I used this from another stackoverflow question: http://jsfiddle.net/Aapn8/3410/ to create circle progress bars.
Except when I'm trying to create more then 1, nothing happens how can you clean fix this without copying the JavaScript and change just 1 var.
This is my code:
.circleWrapper {
width: 250px;
float: left;
}
.circleText {} .circleTextSmall {} #graph div {
position: relative;
margin: 80px;
width: 220px;
height: 220px;
}
#graph canvas {
display: block;
top: 0;
left: 0;
}
#graph span {
color: #555;
display: block;
line-height: 220px;
text-align: center;
width: 220px;
font-family: sans-serif;
font-size: 40px;
font-weight: 100;
margin-left: 5px;
}
#graph input {
width: 200px;
}
<div class="circleWrapper">
<div class="chart" id="graph" data-percent="50"></div>
<div class="circleText">HTML/CSS</div>
<div class="circleTextSmall">Small text</div>
</div>
<div class="circleWrapper">
<div class="chart" id="graph" data-percent="45"></div>
<div class="circleText">PHP</div>
<div class="circleTextSmall">Small text</div>
</div>
var els = document.getElementsByClassName("chart");
for(var i=0; i < els.length; i++){
var el = els[i];
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
}
div {
position:relative;
margin:80px;
width:220px; height:220px;
}
canvas {
display: block;
position:absolute;
top:0;
left:0;
}
span {
color:#555;
display:block;
line-height:220px;
text-align:center;
width:220px;
font-family:sans-serif;
font-size:40px;
font-weight:100;
margin-left:5px;
}
input {
width: 200px;
}
span {
}
<div class="chart" data-percent="88"></div>
<div class="chart" data-percent="78"></div>
Use functions
Put your code inside a function which accepts some way of identifying a particular element, then call that function multiple times. Here's a fork of that fiddle as a working example:
function startGraph(el) { // turn it into a function which accepts an element
// (Nothing else has changed)
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
}
Assuming each element has class="chart" then you can get all the elements and call the function with each one:
// Get all charts:
var myCharts=document.getElementsByClassName("chart");
// For each one..
for (var i in myCharts) {
// Start it:
startGraph(myCharts[i]);
}
You have used the graph ID twice.
You can only use an ID once per document.
The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).
More information on this can be found here.
Change the ID to something else and change the JS to interact with both elements.
This can for example be done with getElementsByClassName(). This function returns an array of elements instead of a single element.
I think it is best if you wrap all your functionality in a function with the following signature:
function startGraph(el) {
...
}
and then call the function from this for-loop:
var elements = document.getElementsByClassName("chart");
var i;
for (i = 0; i < x.length; i++) {
startGraph(elements[i]);
}
More information on that can be found here.
All you need to do is to define unique ids in your HTML, and define an array of all your graph elements and loop through the logic, see this as an example:
var elements = [{
'id': 'graph1'
}, {
'id': 'graph2'
}];
for (var i = 0; i < elements.length; i++) {
var el = document.getElementById(elements[i]['id']);
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
}
div {
position: relative;
margin: 80px;
width: 220px;
height: 220px;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
span {
color: #555;
display: block;
line-height: 220px;
text-align: center;
width: 220px;
font-family: sans-serif;
font-size: 40px;
font-weight: 100;
margin-left: 5px;
}
input {
width: 200px;
}
span {}
<div class="chart" id="graph1" data-percent="88"></div>
<div class="chart" id="graph2" data-percent="25"></div>
first of all, i tried this progress bar:
http://jsfiddle.net/Aapn8/3410/
and i encountered 2 problems:
It was messing my WHOLE page's css because the progress bar's elements didnt have ids and i couldnt really fix it
I wasnt able to edit the percentage via javascript.
I need a circular progress bar that i can control with javascript to add 1% to the percent value every second
i tried to do this via JS to set the progress bar's percentage but it didnt work
var x=0;
function update(y){
document.getElementById("percent").setAttribute("data-percent",y)
}
setInterval(function(){ if (x < 10){x = x+1; update(x);} else {exit;} }, 1000);
Try this, it should not mess with your css.
var el = document.getElementById('graph'); // get canvas
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
var handle = setInterval(function() {
options.percent++;
if(options.percent > 100) {
clearInterval(handle);
return;
}
drawCircle('#555555', options.lineWidth, options.percent / 100);
span.textContent = options.percent + '%';
}, 1000);
#graph div {
position:relative;
margin:80px;
width:220px; height:220px;
}
#graph canvas {
display: block;
position:absolute;
top:0;
left:0;
}
#graph span {
color:#555;
display:block;
line-height:220px;
text-align:center;
width:220px;
font-family:sans-serif;
font-size:40px;
font-weight:100;
margin-left:5px;
}
#graph input {
width: 200px;
}
<div class="chart" id="graph" data-percent="1"></div>