How to divide the Circles into 24/7 equal parts using canvas? - javascript

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Growing Circles</title>
</head>
<body>
<canvas id="c" width="960" height="720"></canvas>
</body>
</html>
JavaScript
var canvas = document.getElementById( "c" ),
ctx = canvas.getContext( "2d" );
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc( 500, 350, 60, 0, 2 * Math.PI, false );
ctx.fillStyle = "#4DA54D";
ctx.fill();
ctx.strokeStyle = "DarkRed";
ctx.stroke();
ctx.beginPath();
ctx.arc( 500, 350, 120, 0, 2 * Math.PI, false );
ctx.strokeStyle = "OliveDrab";
ctx.stroke();
ctx.beginPath();
ctx.arc( 500, 350, 180, 0, 2 * Math.PI, false );
ctx.strokeStyle = "#530053";
ctx.stroke();
ctx.beginPath();
ctx.arc( 500, 350, 240, 0, 2 * Math.PI, false );
ctx.strokeStyle = "#208181";
ctx.stroke();
ctx.beginPath();
ctx.arc( 500, 350, 300, 0, 2 * Math.PI, false );
ctx.strokeStyle = "#CC7A00";
ctx.stroke();
ctx.beginPath();
ctx.arc( 500, 350, 360, 0, 2 * Math.PI, false );
ctx.strokeStyle = "#205450";
ctx.stroke();
I want to divide This demo into 24 hours timeline by using lines. I tried few but not up-to mark.It is going very big in code!
Is there any other way to solve this in small piece of code like using slice as in Tried demo ?
Tried Demo
My Requirement is to do as This demo.
I want to have This demo to be sliced 24/7 where 24 represent hours and 7 for days.
Further Requirement :: Even i must be able to access the particular arc which i want depending on the day and hour !
Finally i want to have a look like this Image I will pass the arguments(Day, hour,Color) and then that particular segment should change the color, as i shown in the Image.
This is how i tried to print the numbers ..
function drawnumbers(){
for(var i=1; i< hours+1;i++){
context.font="18px sans-serif";
context.fillText(+i,20+i*30,20+i*30);
}
}but i want them on the outer circle as in png Image

Although Harsh has already provided a very useful answer, it relates to the wireframe drawing which you depicted.
I thought it would also be useful to show you how you could achieve the drawing of the individual segments.
I think you have asked for a little too much in your PNG as we would practically be creating your project for you, but with my answer and Harsh's answer I believe you can get what you want:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// centre or center for US :) the drawing
var x = canvas.width / 2;
var y = canvas.height / 2;
// number of days
var days = 7;
// number of hours
var hours = 24;
// one segment represents an hour so divide degrees by hours
var segmentWidth = 360 / hours;
// begin at 0 and end at one segment width
var startAngle = 0;
var endAngle = segmentWidth;
// how thick you want a segment
var segmentDepth = 30;
function init() {
for (var i = 1; i <= days; i++) {
drawSegments(i * segmentDepth);
}
}
function drawSegments(radius) {
for (var i = 0; i < hours; i++) {
context.beginPath();
context.arc(x, y, radius,
(startAngle * Math.PI / 180), (endAngle * Math.PI / 180), false);
context.lineWidth = segmentDepth;
context.strokeStyle = '#' +
(Math.random() * 0xFFFFFF << 0).toString(16);
context.stroke();
// increase per segment
startAngle += segmentWidth;
endAngle += segmentWidth;
}
}
// start drawing our chart
init();
See my http://jsfiddle.net/U2tPJ/6/ demo.

Man, you are doing PROGRAMMING, so why are you afraid of using the tools? Use loops and variables.
Dial
var canvas = document.getElementById( "c" ),
ctx = canvas.getContext( "2d" ),
strokes = ["DarkRed", "OliveDrab", "#530053", "#208181", "#CC7A00", "#205450"];
ctx.lineWidth = 3;
for(var i=0; i<7; i++) {
ctx.beginPath();
ctx.arc( 500, 350, 420-60*i, 0, 2 * Math.PI, false );
if(i==6) {
ctx.fillStyle = "#4DA54D";
ctx.fill();
}
ctx.strokeStyle = strokes[i];
ctx.stroke();
}
// Now do the same for the 24 spokes (Use mathematical formulae)
// this is just from the top of my head, may need some adjustment
angle = 360/25; // you have 24 spokes, so 25 sectors (first and last one overlap or are the same)
for(var j=0; j<24; j++) {
ctx.beginPath();
ctx.moveTo(500, 350);
ctx.lineTo(500+420*Math.sin(angle*j), 350-420*Math.cos(angle*j));
ctx.strokeStyle = "blue";
ctx.stroke();
}
Labels
For printing labels on the dial:
angle = 360/23;
for(var i=0; i<23; i++) {
x = <centerX> + <radius> * Math.sin(angle*i*Math.PI/180) // convert from radian to angle
y = <centerY> - <radius> * Math.cos(angle*i*Math.PI/180)
context.fillText(i+1, x, y);
}

Related

JavaScript/jQuery --> Run the function whose name matches the data string inside THIS clicked link

How to run the function whose name matches the data string inside THIS clicked link?
// From line 0 to 36 there are uninteresting details which are ment to set up canvas.
// The 2 functions corresponding to my question are on lines 47 and 115.
// First function (line 47) counts up to 94%, and Second Function (line 115) counts up to 54%.
// You need the line --> var sim = setInterval(progressSim, 40); <-- on line 102 to fire the function.
var ctx = document.getElementById('my_canvas').getContext('2d');
var ctx2 = document.getElementById('my_canvas2').getContext('2d');
var al = 0;
var start = 4.72;
var cw = ctx.canvas.width;
var ch = ctx.canvas.height;
var diff;
var greenPart = ctx.createLinearGradient(0, 0, 0, 100);
greenPart.addColorStop(0, '#0f2596');
greenPart.addColorStop(1, '#0ea5e8');
var whitePart = ctx.createLinearGradient(0, 0, 0, 100);
whitePart.addColorStop(0, '#fff');
whitePart.addColorStop(1, '#0e97df');
var width = 3;
var width2 = 1;
ctx2.save();
ctx2.beginPath();
ctx2.rect(-width, -width, 70 + width, 70 + width * 2);
ctx2.clip();
// Then we draw the left half
ctx2.beginPath();
ctx2.arc(35, 35, 45, 0, Math.PI * 4, false);
ctx2.fillStyle = '#fff';
ctx2.fill();
ctx2.restore();
// This is the First Function
function progressSim() {
diff = ((al / 100) * Math.PI * 2 * 10).toFixed(2);
ctx.clearRect(0, 0, cw, ch);
ctx.lineWidth = width;
ctx.fillStyle = '#1c295c';
ctx.textAlign = 'center';
ctx.font = "bold 19px Arial";
ctx.fillText(al + '%', cw * .54, ch * .54 + 2, cw);
// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width2, -width2, 100, 100 + width2 * 2);
ctx.clip();
ctx.lineWidth = width2;
// Then we draw the left half
ctx.strokeStyle = "#d7ecf6";
ctx.beginPath();
ctx.arc(50, 50, 45, 0, Math.PI * 4, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
// Then we make a clipping region for the right half
ctx.save();
ctx.beginPath();
ctx.rect(50, -width, 50 + width, 100 + width * 2);
ctx.clip();
// Then we draw the right half
ctx.strokeStyle = greenPart;
ctx.beginPath();
ctx.lineCap = 'round';
ctx.arc(50, 50, 45, 4.78, diff / 10 + start, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width, -width, 50 + width, 100 + width * 2);
ctx.clip();
// Then we draw the left half
ctx.strokeStyle = whitePart;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.arc(50, 50, 45, start, diff / 10 + start, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
if (al >= 94) {
clearTimeout(sim);
// Add scripting here that will run when progress completes
}
al++;
}
var sim = setInterval(progressSim, 40);
// This is the Second Function
function progressSim2() {
diff = ((al / 100) * Math.PI * 2 * 10).toFixed(2);
ctx.clearRect(0, 0, cw, ch);
ctx.lineWidth = width;
ctx.fillStyle = '#1c295c';
ctx.textAlign = 'center';
ctx.font = "bold 19px Arial";
ctx.fillText(al + '%', cw * .54, ch * .54 + 2, cw);
// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width2, -width2, 100, 100 + width2 * 2);
ctx.clip();
ctx.lineWidth = width2;
// Then we draw the left half
ctx.strokeStyle = "#d7ecf6";
ctx.beginPath();
ctx.arc(50, 50, 45, 0, Math.PI * 4, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
// Then we make a clipping region for the right half
ctx.save();
ctx.beginPath();
ctx.rect(50, -width, 50 + width, 100 + width * 2);
ctx.clip();
// Then we draw the right half
ctx.strokeStyle = greenPart;
ctx.beginPath();
ctx.lineCap = 'round';
ctx.arc(50, 50, 45, 4.78, diff / 10 + start, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width, -width, 50 + width, 100 + width * 2);
ctx.clip();
// Then we draw the left half
ctx.strokeStyle = whitePart;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.arc(50, 50, 45, start, diff / 10 + start, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
if (al >= 54) {
clearTimeout(sim);
// Add scripting here that will run when progress completes
}
al++;
}
* {
margin: 0;
padding: 0;
}
a {
display: inline-block;
text-decoration: none;
text-transform: uppercase;
font-size: 20px;
margin: 10px 30px;
color: teal;
}
one
two
<div class="canvaswrap">
<canvas id="my_canvas2" width="70" height="70"></canvas>
<canvas id="my_canvas" width="100" height="100"></canvas>
</div>
When I click the given link (there are 2 links) I want to store its data attribute inside variable and fire the function whose name matches that stored data attribute string.
For example, when I click 2nd link I want to store its data attribute progressSim2 inside variable and fire the function progressSim2().
First function counts up to 94% whereas the Second function counts up to 54%.
Below my attempt ( I am using jQuery):
$(function () {
jQuery('a').click(function(e) {
e.preventDefault();
var storedata = $($.attr(this, 'data'));
jQuery("#canvas1").fadeIn();
var sim = setInterval(storedata , 40);
});
});
The closest way to your question, in my opinion: create a "mapping" object and call upon its properties:
var OBJECT_MAPS = {
'dummy1': function () => {},
'dummy2': function () => {}
}
Use it like this:
some_event_handler(item_name) => {
// Check if function exists in map, and it is actually a function
if (typeof OBJECT_MAPS[item_name] === 'function'){
// A) If execution context doesn't matter
OBJECT_MAPS[item_name](param1, param2, ...);
// B) If execution context matters (change "this" to required context)
OBJECT_MAPS[item_name].call(this, param1, param2, ...)
} else {
console.error('Callback by name ' + item_name + ' does not exist');
}
}
I would discourage using global functions bound to window object as this is generally considered a bad practice. Manipulating and overriding global objects is very easy from browser's console, so anyone would be able to change how your functions work. Always hide your functionality from bad people, even if it is inside javascript :)
Other ways to do this:
Use switch statement to "switch" between function callbacks.
Make your callbacks "event listeners". Emit events when item is chosen.
Also, User by name "Hikarunomemory" noticed incorrect usage of attr function in your code, please see his response.
Hope this helps you.
If you declare you progressSim and progressSim2 methods globally. You can call them like this:
window[$.attr(this, 'data')]()
or you can store link to them in another Object:
object[$.attr(this, 'data')]()
var storedata = $($.attr(this, 'data')); is incorrect.
To get a attribute, you should use $(this).attr('data') or $.attr(this, 'data')
Then, set the functions as a global variable, and use window['funcName']() to execute the function.
Here's a simple demo:
$('a').on('click', function(e) {
e.preventDefault();
var storedata = $(this).attr('data');
console.log(storedata)
window[storedata]();
})
var progressSim = function() {
console.log('execute function1')
}
var progressSim2 = function() {
console.log('execute function2')
}
* {
margin: 0;
padding: 0;
}
a {
display: inline-block;
text-decoration: none;
text-transform: uppercase;
font-size: 20px;
margin: 10px 30px;
color: teal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
one
two
<div class="canvaswrap">
<canvas id="my_canvas2" width="70" height="70"></canvas>
<canvas id="my_canvas" width="100" height="100"></canvas>
</div>
As a side note,
eval() is a dangerous function, which executes the code it's passed
with the privileges of the caller. If you run eval() with a string
that could be affected by a malicious party, you may end up running
malicious code on the user's machine with the permissions of your
webpage / extension. More importantly, a third-party code can see the
scope in which eval() was invoked, which can lead to possible attacks
in ways to which the similar Function is not susceptible.
From MDN
the function "eval" runs string as a code,
example:
function progressSim(){console.log("sim is ok")}
eval("progressSim()")

Canvas figures moves to the right side

Here is the code:
$(document).ready(function() {
var canvas = $("#canvas")[0];
var context = canvas.getContext("2d");
canvas.width = window.innerWidth
canvas.height = window.innerHeight
polygon(context, 120, 120, 50, 12);
context.stroke();
})
function polygon(ctx, x, y, radius, sides) {
if (sides < 3) return;
var a = ((Math.PI * 2) / sides);
ctx.beginPath();
ctx.translate(x, y);
ctx.moveTo(radius, 0);
for (var i = 1; i < sides; i++) {
ctx.lineTo(radius * Math.cos(a * i), radius * Math.sin(a * i));
}
ctx.closePath();
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<canvas id="canvas">OOPS.. Upgrade your Browser</canvas>
This code works fine. BUT each of my polgon appears at wrong place. For example I call
polygon(context, 120,120,50,12);
and
polygon(context, 120,220,50,12);
and the second polygon appears at x=220, y=220
I mean, they moves in the right side, but they should appear one under another with the same x coordinates.
After drawing the shape you need to translate it back to the original position so the next shape is drawn from the same relative location as the first.
ctx.translate(-x, -y);
$(document).ready(function() {
var canvas = $("#canvas")[0];
var context = canvas.getContext("2d");
canvas.width = window.innerWidth
canvas.height = window.innerHeight
polygon(context, 120, 120, 50, 12);
context.stroke();
polygon(context, 120,220,50,12);
context.stroke();
})
function polygon(ctx, x, y, radius, sides) {
if (sides < 3) return;
var a = ((Math.PI * 2) / sides);
ctx.beginPath();
ctx.translate(x, y);
ctx.moveTo(radius, 0);
for (var i = 1; i < sides; i++) {
ctx.lineTo(radius * Math.cos(a * i), radius * Math.sin(a * i));
}
ctx.closePath();
ctx.translate(-x, -y);
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<canvas id="canvas">OOPS.. Upgrade your Browser</canvas>
Reset the translation matrix to the identity matrix before drawing each shape:
context.setTransform(1, 0, 0, 1, 0, 0);
I think it happens because of:
ctx.translate(x, y);
If you look closely at HTML canvas translate() Method Definition and Usage you will see that translate() method remaps the (0,0) position of the canvas instead of setting starting point for your drawing. So if you do function call like this:
ctx.translate(120, 120);
ctx.translate(120, 220);
You actually moving registration point of canvas twice. First time it will be moved by (120,120) and later it will be moved by (120,220), so your first polygon will be drawed correctly but the second will be drawed on position (240,340), because coordinates of both starting points will eventually be summed.
You are using the same 2d context over and over for your polygons. The context will save the state of your translations, so consecutive translations add up. You could "revert" the effect of translations by translating with same-negative-values at the end of each polygon call.
$(document).ready(function() {
var canvas = $("#canvas")[0];
var context = canvas.getContext("2d");
canvas.width = window.innerWidth
canvas.height = window.innerHeight
polygon(context, 120, 120, 50, 12);
context.stroke();
polygon(context, 120, 220, 50, 12);
context.stroke();
})
function polygon(ctx, x, y, radius, sides) {
if (sides < 3) return;
var a = ((Math.PI * 2) / sides);
ctx.beginPath();
ctx.translate(x, y);
ctx.moveTo(radius, 0);
for (var i = 1; i < sides; i++) {
ctx.lineTo(radius * Math.cos(a * i), radius * Math.sin(a * i));
}
ctx.closePath();
ctx.translate(-1 * x, -1 * y);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<canvas id="canvas">OOPS.. Upgrade your Browser</canvas>

Sharpen the draw in an HTML5 canvas

Today I started learning how to work with canvas by doing a basic loading circle animation. Everything works perfect in small res (ca. 100×100 px) but when I tried much larger it all went distorted and blurred and it looks really bad. So this is my question: Can I somehow turn on some anti-aliasing on or somehow make it more sharpen? I already found plenty of sharpening algorithms but for images and I’m not sure if it will work with this.
Circle loading example: (code is not perfect or even finished because I’m still stuck on that blur)
JSFiddle
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var int_count = 0;
var circ_angle = 1.5;
var count = 10;
var interval = setInterval(function() {
if (int_count == count) {
clearInterval(interval);
}
ctx.clearRect(0, 0, 1000, 1000);
ctx.beginPath();
ctx.arc(100, 70, 50, 1.5 * Math.PI, -1 * Math.PI, true);
ctx.lineWidth = 1;
ctx.strokeStyle = "#717171";
ctx.stroke();
ctx.beginPath();
//1.5 = 0%; 1 = 1/4; 0.5 = 2/4; 0 = 3/4 -1 = full
ctx.font = "40px sarpanch";
ctx.arc(100, 70, 50, 1.5 * Math.PI, circ_angle * Math.PI, true);
//color
if (int_count >= 5 && int_count < 10) {
ctx.strokeStyle = "#ff8000";
}
else if (int_count >= 9) {
ctx.strokeStyle = "#F00";
}
else {
ctx.strokeStyle = "#3a9fbe";
}
ctx.fillText("" + int_count + "", 88, 83);
ctx.lineWidth = 3;
ctx.stroke();
int_count += 1;
circ_angle += (-0.2);
}, 500);
Add the following attributes :
width="759" height="394"
to your <canvas> instead of specifying them in your css
Never resize your canvas with CSS. Instead, set the canvas size with the width and height attributes:
<canvas id="canvas" width="759" height="394"></canvas>
Remove the CSS rules for the canvas.
Next, you’ll have to scale every part with JavaScript:
Working demo
// …
ctx.arc(150, 150, 100, 1.5*Math.PI,-1*Math.PI,true); // instead of 100, 70, 50
// …
ctx.font = "60px sarpanch"; // instead of 40px
ctx.arc(150, 150, 100, 1.5*Math.PI,circ_angle*Math.PI,true); // instead of 100, 70, 50
// …
ctx.fillText(int_count, 130, 170); // instead of 88, 83
// …

Issue on Drawing Multiple Circles on HTML5 Canvas

Can you please take a look at this demo and let me know how I can draw multiple circles in a canvas with different coordinate without repeating bunch of codes?
As you can see on Demo and following code
var ctx = $('#canvas')[0].getContext("2d");
ctx.fillStyle = "#00A308";
ctx.beginPath();
ctx.arc(150, 50, 5, 0, Math.PI * 2, true);
ctx.arc(20, 85, 5, 0, Math.PI * 2, true);
ctx.arc(160, 95, 5, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
I tried to have them under ctx but it is not correct so I tried to use for loop to create 50 points but I have issue on repeating and adding code like ctx.fill(); for all of them.
Can you please let me know how I can fix this?
Thanks
Constantly creating and closing new paths is not good advice.
You should batch together all fills / strokes of the same style, and execute them in a single draw call. The performance difference between these approaches becomes apparent very quickly with increasing polygon count.
The way to go about it is to move the pen and make the path construction call for each circle; stroke/fill in the end in one shot. However, there's a quirk involved here. When you have the point moved to the center and draw the circle, you'd still see a horizontal radius line, drawn from the center of the circle, to the circumference.
To avoid this artefact, instead of moving to the center, we move to the circumference. This skips the radius drawing. Essentially all these commands are for tracing a path and there's no way to describe a discontinuity without calling closePath; usually moveTo does it but HTML5 canvas API it doesn't. This is a simple workaround to counter that.
const pi2 = Math.PI * 2;
const radius = 5;
ctx.fillStyle = '#00a308';
ctx.beginPath();
for( let i=0, l=coords.length; i < l; i++ )
{
const p = coords[i],
x = p.x,
y = p.y;
ctx.moveTo( x + radius, y ); // This was the line you were looking for
ctx.arc( x, y, radius, 0, pi2 );
}
// Finally, draw outside loop
ctx.stroke();
ctx.fill();
Also worth considering, is using transformations, and drawing everything relative to a local frame of reference.
ctx.fillStyle = '#00a308';
ctx.beginPath();
for( let i=0, l=coords.length; i < l; i++ )
{
const p = coords[i];
ctx.save();
ctx.translate( p.x + radius, p.y );
ctx.moveTo( 0, 0 );
ctx.arc( 0, 0, radius, 0, pi2 );
ctx.restore();
}
ctx.stroke();
ctx.fill();
This is because you are not closing the path, either using fill() or closePath() will close the path so it does not try and connect all the items. fill() fills in the circles and closes the path so we can just use that. Also you need to use beginPath(), so that they are separate from each other. Here is your three circles:
var coords = [ [150,50], [20,85], [160,95] ];
for(var i = 0; i < coords.length; i++){
ctx.beginPath();
ctx.arc(coords[i][0], coords[i][1], 5, 0, Math.PI * 2, true);
ctx.fill();
}
To not repeat a bunch of code and have unique coordinates store your X and Y position in an array and use a for loop to go through it.
Update:
A more efficient way to do which achieves the same effect this would be to only use a single path and use moveTo() instead of creating a new path when drawing each circle:
ctx.beginPath();
for(var i = 0; i < coords.length; i++){
ctx.moveTo(coords[i][0], coords[i][1]);
ctx.arc(coords[i][0], coords[i][1], 5, 0, Math.PI * 2, true);
}
ctx.fill();
ctx.beginPath();
points.forEach(point => {
ctx.moveTo( point.x, point.y );
ctx.arc(point.x,point.y,1,0,Math.PI*2,false);
});
ctx.fill();
You can easily create several circles with a for loop. You really just need to draw an arc and fill it each time. Using your example, you could do something like this.
var ctx = $('#canvas')[0].getContext("2d");
ctx.fillStyle = "#00A308";
for (var i = 0; i < 3; i++) {
ctx.arc(50 * (i+1), 50 + 15 * i, 5, 0, Math.PI * 2, true);
ctx.fill();
}
Example Fiddle of lots of circles in different locations drawn in a loop.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext( '2d' );
var cx = canvas.width/2;
var cy = canvas.height/2;
ctx.fillStyle = "#00A308";
var total_circles = 50;
var radius = 100;
for(i = 0; i < total_circles; i++){
var angle = i * 2 * Math.PI/total_circles;
var x = cx + Math.cos(angle) * radius;
var y = cy + Math.sin(angle) * radius;
ctx.beginPath();
ctx.arc(x, y, 2, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}

Can I plot HTML5 Canvas x/y points programatically using jQuery with external JSON data?

I've got an HTML5 canvas 'join the dots' type thing going - 2 lines with dots at their angle points - this is fine but I want to plot the X coordinates programatically with external JSON data (pulled from a 'local' server so won't need to be JSONP) - I hope I explain this clearly ...
I'm not trying to convert the JSON data into new DOM elements, but instead I need to apply the data to the actual script which maps the canvas coordinates. Ideally I want to use jQuery for this and my guess is that I will need to parse a JSON object via .getJSON(), but this is where I need some help.
Both X and Y coordinates are currently initiated with hard-coded variables in the canvas script but I want the JSON data to parse into the X variable programatically (the Y co-ords can stay hard coded and work fine for both lines).
Here's a fiddle of what I have so far: http://jsfiddle.net/ByT58/6/
Here's the markup/script for reference - and big thanks in advance for any help!:
HTML:
<div class="canvas-wrap">
<canvas id="myCanvas" width="200" height="115"></canvas>
</div>
Here's how the external JSON would look:
{
"red": {
"r01x": 20,
"r02x": 149,
"r03x": 50
},
"blue": {
"b01x": 80,
"b02x": 179,
"b03x": 20
}
}
JS:
var ctx = document.getElementsByTagName('canvas')[0].getContext('2d');
// set attributes for all circles
var radius = 7;
// set attributes for all lines
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
// set X co-ords for Red
var r01x = 20;
var r02x = 149;
var r03x = 50;
// set X co-ords for Blue
var b01x = 80;
var b02x = 179;
var b03x = 20;
// Set default Y coordinates for both Red and Blue
var y01 = 20;
var y02 = 50;
var y03 = 100;
// RED dots
ctx.beginPath();
ctx.fillStyle = "#E51919";
ctx.arc(r01x, y01, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#E51919";
ctx.arc(r02x, y02, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#E51919";
ctx.arc(r03x, y03, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
// RED line
ctx.beginPath();
ctx.moveTo(r01x, y01);
ctx.lineTo(r02x, y02);
ctx.lineTo(r03x, y03);
ctx.strokeStyle = "#E51919";
ctx.stroke();
ctx.closePath();
// BLUE dots
ctx.beginPath();
ctx.fillStyle = "#133175";
ctx.arc(b01x, y01, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#133175";
ctx.arc(b02x, y02, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#133175";
ctx.arc(b03x, y03, radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
// BLUE line
ctx.beginPath();
ctx.moveTo(b01x, y01);
ctx.lineTo(b02x, y02);
ctx.lineTo(b03x, y03);
ctx.strokeStyle = "#133175";
ctx.stroke();
ctx.closePath();
If you were to put your JSON data into the form:
{
red: { color: "#E51919", x: [20,149,50] },
blue: { color: "#133175", x: [80,179,20] }
}
Your draw function would look something like (jsFiddle here):
function draw(data) {
var ctx = document.getElementsByTagName('canvas')[0].getContext('2d');
// set attributes for all circles
var radius = 7;
// set attributes for all lines
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
var y = [20,50,100];
for(var key in data) {
var x = data[key].x;
ctx.fillStyle = data[key].color;
for(var i = 0; i < x.length; ++i) {
ctx.beginPath();
ctx.arc(x[i], y[i], radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
}
ctx.beginPath();
ctx.moveTo(x[0], y[0]);
ctx.lineTo(x[1], y[1]);
ctx.lineTo(x[2], y[2]);
ctx.strokeStyle = data[key].color;
ctx.stroke();
ctx.closePath();
}
}
draw({
red: { color: "#E51919", x: [20,149,50] },
blue: { color: "#133175", x: [80,179,20] }
});
Using JQuery to retrieve the JSON data from the server use jQuery.getJSON() or jQuery.ajax()
for example (no error handling...):
$.getJSON('path/data.json', function(data, textStatus, jqXHR) {
console.log(textStatus);
draw(data);
})
.fail(function( jqXHR, textStatus, errorThrown) { console.log(textStatus + " :: " + errorThrown ); });

Categories