How to use the same JS for same HTML multiple times - javascript

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>

Related

Progress bar view without rotating around does not work

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>

Javascript/Canvas Jquery Guessing game time loop

Please help I'm so stuck. I've been coding this for almost 1 month now and I'm more confused now than when I started. Here's a snippet :
const $inputs = $("#number input")
const $form = $("#number");
$inputs.on("input", function() {
if (this.value.length == this.maxLength) {
const $next = $(this).next('#number input');
if ($next.length) $next.focus();
if ($inputs.filter(function() {
return this.value !== ""
}).length === $inputs.length) {
$form.submit();
checkInput();
}
}
});
Here's the JSfiddle : https://jsfiddle.net/viwe/18yhtuo6/2/
Desired behaviour : user must enter the time, code must check the user's answer and keep a score of correct and incorrect answers. This must all happen within a given game time. (ideally I would love to have a drop-down menu and select the game time from there (extra) but for now a just need the code to work.
Stuck point : Page reloads every time user submits an answer (Thereby restarting the scores and time left)
A number of things
I created some global vars to hold the time
I moved the createTime code into its own function to be reused
cleaned up some code
The script does not time out - that will be next question for you
https://jsfiddle.net/mplungjan/3mbqw80h/
function createTime() {
// create new date object and randomize the time, storing hr,min and sec in own variables
const now = new Date();
let hours = now.getUTCHours() * Math.random();
let minutes = now.getUTCMinutes() * Math.random();
let seconds = now.getUTCSeconds() * Math.random();
// Format the time variables
hours = Math.round(hours.toLocaleString('en-US', {
hour: 'numeric', // numeric, 2-digit
}));
minutes = Math.round(minutes.toLocaleString('en-US', {
minute: 'numeric', // numeric, 2-digit
}));
seconds = Math.round(seconds.toLocaleString('en-US', {
second: 'numeric', // numeric, 2-digit
}));
return {
hours,
minutes,
seconds
}
}
let time = createTime();
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
let correctAnswers = [];
let incorrectAnswers = [];
drawClock();
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawNumbersSecs(ctx, radius);
drawTime(ctx, radius);
}
function drawTime(ctx, radius) {
let {
hours,
minutes,
seconds
} = time;
// console.log(hour)
//hour
// Calculate the angle of the hour hand, and draw it a length
// (50% of radius), and a width (7% of radius):
hours = hours % 12;
hours = (hours * Math.PI / 6) + (minutes * Math.PI / (6 * 60)) + (seconds * Math.PI / (360 * 60));
drawHand(ctx, hours, radius * 0.5, radius * 0.04);
//minute
minutes = (minutes * Math.PI / 30) + (seconds * Math.PI / (30 * 60));
drawHand(ctx, minutes, radius * 0.7, radius * 0.03);
// second
seconds = (seconds * Math.PI / 30);
drawHand(ctx, seconds, radius * 0.9, radius * 0.02);
}
function drawHand(ctx, pos, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0, 0);
ctx.rotate(pos);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.rotate(-pos);
}
function drawFace(ctx, radius) {
var grad;
// face
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'black';
ctx.strokeStyle = 'white';
ctx.fill();
// outer ring
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.02);
grad.addColorStop(0, '#333');
// grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#fff');
ctx.strokeStyle = "white";
ctx.lineWidth = radius * 0.02;
ctx.stroke();
// inner circle
ctx.beginPath();
ctx.arc(0, 0, radius * 0.04, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
// Set the font size (of the drawing object) to 15% of the
// radius:
ctx.font = radius * 0.15 + "px arial";
// Set the text alignment to the middle and the center of the
// print position:
ctx.textBaseline = "middle";
ctx.textAlign = "center";
// Calculate the print position (for 12 numbers) to 85% of the
// radius, rotated (PI/6) for each number:
for (num = 1; num < 13; num++) {
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius * 0.85);
ctx.rotate(-ang);
}
}
// Draw the minute / second numbers
function drawNumbersSecs(ctx, radius) {
let ang;
let num;
ctx.font = radius * 0.06 + "px helvetica";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
for (num = 1; num < 61; num++) {
ang = num * Math.PI / 30;
ctx.rotate(ang);
ctx.translate(0, -radius * 1.06);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius * 1.06);
ctx.rotate(-ang);
}
}
// Evaluate the user's input
function checkInput() {
let {
hours,
minutes,
seconds
} = time;
let uHr = uHrs.value;
let uMin = uMins.value;
let uSec = uSecs.value;
const m = document.querySelector("h2");
if (uHr == hours && uMin == minutes && uSec == seconds) {
correctAnswers.push({
"time": time,
"answer": {
uHr,
uMin,
uSec
}
})
console.log(correctAnswers);
m.style.background = "green";
m.innerHTML = "correct";
} else {
incorrectAnswers.push({
"time": time,
"answer": {
uHr,
uMin,
uSec
}
})
console.log(incorrectAnswers);
m.style.background = "red";
m.innerHTML = "incorrect"
}
$("#right").html("Correct: " + correctAnswers.length);
$("#wrong").html("Incorrect: " + incorrectAnswers.length);
console.log(correctAnswers.length)
document.getElementById("number").reset();
time = createTime();
setTimeout(drawClock, 1000);
}
// Jump to next input box and run checkInput
$(function() {
const $inputs = $("#number input"),
$form = $("#number");
$inputs.on("input", function() {
if (this.value.length == this.maxLength) {
const $next = $(this).next('#number input');
if ($next.length) $next.select().focus();
if ($inputs.filter(function() {
return this.value.trim() !== ""
}).length === $inputs.length) {
checkInput();
}
}
});
})
* {
margin: 0;
padding: 0;
}
body {
background-color: black;
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
}
.hide {
display: none;
}
.container {
display: block;
position: relative;
max-width: 800px;
left: 30%;
overflow: none;
}
canvas {
margin: 1em;
}
form input {
display: inline-flex;
position: relative;
left: 12.5%;
font-size: 1.3em;
padding: 0.25em;
width: 4em;
margin-bottom: 0.3em;
border-radius: 1em;
text-align: center;
}
#keyframes hello {
0% {
opacity: 0;
}
25% {
opacity: 1;
}
75% {
opacity: 1;
}
100% {
opacity: 1;
}
}
h2 {
position: relative;
max-width: 460px;
text-align: center;
margin: 1em;
padding: 0.5em;
font-size: 1.3em;
border-radius: 1em;
color: #fff;
animation-name: hello;
animation-duration: 4s;
}
#score {
font-size: 1em;
color: white;
text-align: center;
position: relative;
left: 6.75em;
display: block;
width: 100%;
max-width: 250px;
height: auto;
margin: 0.5em;
padding: 0.3em 1em;
border: 2px solid white;
border-radius: 2em;
}
form button {
margin: 0 2em;
padding: 0 0.6em;
}
#right {
color: green;
}
#wrong {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<canvas id="canvas" width="520" height="520"></canvas>
<div>
<form id="number">
<input placeholder="hr" type="number" maxlength="2" value="" id="uHrs" pattern="[1-12]" autofocus />
<input placeholder="min" type="number" maxlength="2" value="" id="uMins" pattern="[0-59]" />
<input placeholder="sec" type="number" maxlength="2" value="" id="uSecs" pattern="[0-59]" />
</form>
</div>
<div id="score">
<h6 id="game_time">Minutes left: </h6>
<h4 id="right">Correct : </h4>
<h4 id="wrong">Incorrect : </h4>
</div>
<h2 id="mark"></h2>
</div>
>

clickable object or shape inside a canvas viewbox window

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidenav a:hover {
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
</style>
</head>
<body>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<div id="main">
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ Menu</span>
<canvas id="canvas" width="600" height="350" style="border:2px solid #d3d3d3;">></canvas>
</div>
<script>
var zoomIntensity = 0.1;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = 90;
var height = 50;
var scale = 1;
var originx = 0;
var originy = 0;
var visibleWidth = width;
var visibleHeight = height;
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
function draw(){
context.fillStyle = "white";
context.fillRect(originx,originy,1000/scale,800/scale);
context.fillStyle = "blue";
context.fillRect(170,50,50,50);
context.fillStyle = "white";
context.fillText('click here',175,70);
}
setInterval(draw, 1000/60);
canvas.onwheel = function (event){
event.preventDefault();
var mousex = event.clientX - canvas.offsetLeft;
var mousey = event.clientY - canvas.offsetTop;
var wheel = event.deltaY < 0 ? 1 : -1;
var zoom = Math.exp(wheel*zoomIntensity);
context.translate(originx, originy);
originx -= mousex/(scale*zoom) - mousex/scale;
originy -= mousey/(scale*zoom) - mousey/scale;
context.scale(zoom, zoom);
context.translate(-originx, -originy);
scale *= zoom;
visibleWidth = width / scale;
visibleHeight = height / scale;
}
function openNav() {
document.getElementById("mySidenav").style.width = "200px";
document.getElementById("main").style.marginLeft = "200px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
</body>
</html>
is there away to make a shape or object clickable on canvas frame or viewbox, even when i zoom in or out, cause all the examples i saw was just a fixed clickable location. for instance google map locations when i zoom in i can click more objects.
is there away to make a shape or object clickable on canvas frame or viewbox, even when i zoom in or out, cause all the examples i saw was just a fixed clickable location. for instance google map locations when i zoom in i can click more objects.
There are two spaces you have to account for, the actual canvas space and the translated space. This means you need to translate the mouse coordinates in order to know where in the space the object is actually located and map it back to the canvas coordinates so you can know if you are clicking on it. This is achieved by keeping track of the offset value you provided in the var originx, but the problem is that there is no way based on my trails at least for you to translate the mouse click location if you use the context.translate(originx, originy) if you both scale and pan the object space.
I have rewritten the code without the use of the translate function by making my own translate function that enables you to translate between the canvas space and object space in order to register a click event on the object regardless of the panned or zoomed in location.
This function also has a click to pan feature so you can click and drag the object screen to where ever you want to object to be positioned.
/*jshint esversion: 8 */
(function() {
const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");
let canvasWidth = 600;
let canvasHeight = 600;
let offset = {
x: 0,
y: 0
};
let pan = {
x: 0,
y: 0
};
var zoomIntensity = 0.1;
let scale = 1;
let mouse = {
x: 0,
y: 0
};
let dragging = false;
let square;
let shapes = [{
x: 170,
y: 50,
w: 50,
h: 50,
color: "blue"
},
{
x: 85,
y: 25,
w: 50,
h: 50,
color: "red"
},
{
x: 50,
y: 100,
w: 50,
h: 50,
color: "green"
},
];
function init() {
canvas.width = canvasWidth;
canvas.height = canvasHeight;
renderCanvas();
}
function drawSquare(x, y, width, height, color) {
context.fillStyle = color;
context.fillRect(x, y, width, height);
}
function objectsToCanvasScreen(x, y) {
const canvasScreenX = Math.floor((x - offset.x) * scale);
const canvasScreenY = Math.floor((y - offset.y) * scale);
return {
x: canvasScreenX,
y: canvasScreenY
};
}
function canvasToObjectsScreen(x, y) {
return {
x: x / scale + offset.x,
y: y / scale + offset.y
};
}
function renderCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
shapes.forEach(({
x,
y,
w,
h,
color
}, index) => {
const {
x: csx,
y: csy
} = objectsToCanvasScreen(x, y);
shapes[index]._x = csx;
shapes[index]._y = csy;
shapes[index]._w = w * scale;
shapes[index]._h = h * scale;
drawSquare(csx, csy, w * scale, h * scale, color);
});
}
canvas.onwheel = function(e) {
const zoom = Math.exp((e.deltaY < 0 ? 1 : -1) * zoomIntensity);
const beforeZoom = canvasToObjectsScreen(mouse.x, mouse.y);
scale *= zoom;
const afterZoom = canvasToObjectsScreen(mouse.x, mouse.y);
offset.x += beforeZoom.x - afterZoom.x;
offset.y += beforeZoom.y - afterZoom.y;
renderCanvas();
};
canvas.onmousedown = function(e) {
if (e.button === 0) {
pan.x = mouse.x;
pan.y = mouse.y;
dragging = true;
}
};
canvas.onmouseup = (e) => (dragging = false);
canvas.onmousemove = function(e) {
mouse.x = e.offsetX;
mouse.y = e.offsetY;
if (dragging) {
offset.x -= (mouse.x - pan.x) / scale;
offset.y -= (mouse.y - pan.y) / scale;
pan.x = mouse.x;
pan.y = mouse.y;
renderCanvas();
}
};
canvas.onclick = function(e) {
shapes.forEach(({
_x,
_y,
_w,
_h,
color
}) => {
const {
x: mousex,
y: mousey
} = canvasToObjectsScreen(mouse.x, mouse.y);
const {
x: squarex,
y: squarey
} = canvasToObjectsScreen(_x, _y);
if (
mousex >= squarex &&
mousex <= _w / scale + squarex &&
mousey >= squarey &&
mousey <= _h / scale + squarey
) {
alert(`${color} clicked!`);
}
});
};
init();
})();
body {
font-family: "Lato", sans-serif;
}
#canvas {
background: #E1BC8B;
}
<body>
<div id="main">
<canvas id="canvas" width="300" height="350"></canvas>
</div>
</body>

How to create more than one circular progress bar?

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

Circular progress bar with percentage controlled via JS

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>

Categories