How to make a graph that dynamically loads from a object - javascript

$(document).ready(function () {
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
function deseneazaGrafic(valori) {
var h = canvas.height;
var w = canvas.width / valori.length;
context.fillStyle = "#DEDEDE";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "red";
context.strokeStyle = "black ";
context.lineWidth = 2;
var f = canvas.height * 0.9 / Math.max.apply(Math, valori);
for (var i = 0; i < valori.length; i++) {
context.beginPath();
context.rect((i + 0.1) * w, h - valori[i] * f, 0.8 * w, valori[i] * f);
context.fill();
context.stroke();
}
}
$("#btnGrafic").click(function () {
deseneazaGrafic(eval("[" + $("#valori").val() + "]"));
});
$("#scrie").click(function(){
});
});
This is my java script. This makes a graph from some written values. How can i change the "valori" to be jsonObject.values?Thanks a lot

As a formal answer (see question comments for details), the function deseneazaGrafic accepts a simple javascript array. Right now it's evaling (ew... bad) the value of a textarea (#valori). You can use any javascript array. When you get the values from your JSON file, just pass it to deseneazaGrafic as its parameter. For example:
var jsonObject = JSON.parse(myJSONString); // the JSON object contains an array called "values"
deseneazaGrafic(jsonObject.values);
That should render the graph just fine assuming the array is parsed correctly.

Related

How to (re)fill circle in canvas - requestAnimationFrame - HTML, JS

how can I fill the "new" canvas circle that appears next to the older one.
There is no problem with rectangle for example:
**
ctx.fillStyle = 'rgba('+quadratto.r+','+quadratto.g+','+quadratto.b+',1)';
quadratto.x += quadratto.speedX;
quadratto.y += quadratto.speedY;
quadratto.speedY += quadratto.speedY*(-0.15);
ctx.fillRect(quadratto.x-quadratto.h/4, quadratto.y-quadratto.h/2, 2, 2);**
What I want to do?
I'm creating animation in canvas where random-sized-color circle will appear and
it will move in a specified direction. The new canvas layaer will appear in the next frame (fps) with a new(old) circle.
var myCanvasPattern = document.createElement('canvas');
myCanvasPattern.width = window.innerWidth;
myCanvasPattern.height = window.innerHeight;
document.body.appendChild(myCanvasPattern);
var ryC = myCanvasPattern.getContext('2d');
function lottery(min, max) {
return Math.floor(Math.random()*(max-min+1))+min;
}
var allQuadro = [];
var fps = 50;
var lastTime = 0;
animationLoop();
function animationLoop(time){
requestAnimationFrame( animationLoop );
if(time-lastTime>=1000/fps){
lastTime = time;
for(var i=0;i<10;i++){
allQuadro.push({
r : lottery(0, 240),
g : lottery(0, 240),
b : lottery(0, 240),
circleR : lottery(10, 30),
x : myCanvasPattern.width/2,
y : myCanvasPattern.height/2,
speedX : lottery(-1000,1000)/100,
speedY : lottery(-1000,1000)/100
})
}
ryC.fillStyle = 'rgba(255,255,255,0.2)';
ryC.fill(0,0,myCanvasPattern.width, myCanvasPattern.height);
for(var i=0; i<allQuadro.length;i++){
var circle = allQuadro[i];
ryC.fillStyle = 'rgba('+circle.r+','+circle.g+','+circle.b+',1)';
circle.x += circle.speedX;
circle.y += circle.speedY;
//HERE's THE PROBLEM BELOW. HOW TO CREATE NEW ONE THAT APPEARS NEXT TO PREVIOUS ONE WITH NEW RANDOM COLOR
ryC.arc(circle.x-circle.circleR/2, circle.y-circle.circleR/2, circleR, 0, 2 * Math.PI);
//ryC.fill();
}
// ryC.fillStyle = 'rgba('+r+','+g+','+b+',1)';
//ryC.arc(x+speedX, y+speedY, circleR, 0, 2 * Math.PI);
//ryC.fill();
}
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
The fillRect() will fill directly to the canvas without going via a path (versus for example rect()).
The arc() on the other hand will add to a path which needs to be filled later. It also require the path to be cleared in-between the calls using beginPath().
A simple way to think about it is to wrap the necessary code into a function that acts like fillRect():
function fillArc() {
ctx.beginPath(); // clear current path
ctx.arc.apply(ctx, arguments); // apply arguments to arc() call
ctx.fill();
// notice that the arc still exist on the path after this call
// so to "truly" behave like fillRect() you could consider an
// additional beginPath() here.. it will depend on your code
}
In action:
var ctx = c.getContext("2d");
ctx.fillStyle = "#09f";
fillArc(70, 70, 70, 0, 6.28);
ctx.fillStyle = "#0a9";
fillArc(220, 70, 70, 0, 6.28);
function fillArc() {
ctx.beginPath();
ctx.arc.apply(ctx, arguments);
ctx.fill();
}
<canvas id=c></canvas>
If you are bold you can also add the method to the context itself before calling getContext():
CanvasRenderingContext2D.prototype.fillArc = function() {
this.beginPath();
this.arc.apply(this, arguments);
this.fill();
}
The use it like any other method:
ctx.fillArc( ... );
CanvasRenderingContext2D.prototype.fillArc = function() {
this.beginPath();
this.arc.apply(this, arguments);
this.fill();
}
var ctx = c.getContext("2d");
ctx.fillStyle = "#09f";
ctx.fillArc(70, 70, 70, 0, 6.28);
ctx.fillStyle = "#0a9";
ctx.fillArc(220, 70, 70, 0, 6.28);
<canvas id=c></canvas>

canvas push object failed

each time when I am reviewing and trying to re-write my code I always got errors and some unexpected issues. I am making a function object called draw() and trying to push it 20 times into an empty array for the animate purpose. the code is as follows:
function draw(){
var r = 20;
var x = Math.random()*canvas.width - r;
var y = Math.random()*canvas.height - r;
ctx.beginPath();
ctx.arc(x,y,r,Math.PI*2,false);
ctx.fillStyle='yellow';
ctx.fill();
}
myArray = [];
for(i=0;i<20;i++){
myArray.push(draw());
}
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
requestAnimationFrame(animate);
for(i=0;i<myArray.length;i++){
myArray[i];
}
}
animate();
When I am checking myArrayobject in the console, it just popped out 20 objects with undefined value, which means there is totally empty inside myArrayobject. I am stuck with this for 2 hours could someone could tell me where I go wrong with this? Thanks in advance.
myArray.push(draw()) calls the draw() function immediately and puts its return value (undefined) into the array. You probably want to push a reference to the function, so omit the ():
myArray.push(draw);
Then, in your for loop, to call the functions from the array you need parentheses:
myArray[i]();
Pushing the same function seems a bit pointless, because you could just directly call the function from your loop without using the array, but I assume you want to set up for the possibility of running some predefined sequence of several different functions that aren't shown.
Anyway, the following demo shows the above changes working in the context of your full code:
var canvas = document.querySelector("canvas")
var ctx = canvas.getContext("2d");
function draw() {
var r = 20;
var x = Math.random() * canvas.width - r;
var y = Math.random() * canvas.height - r;
ctx.beginPath();
ctx.arc(x, y, r, Math.PI * 2, false);
ctx.fillStyle = 'yellow';
ctx.fill();
}
myArray = [];
for (i = 0; i < 20; i++) {
myArray.push(draw); // this line changed
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(animate);
for (i = 0; i < myArray.length; i++) {
myArray[i](); // this line changed
}
}
animate();
<canvas></canvas>

Canvas creating two separate animated waterfall objects

I am trying to create a template for initiating as many waterfall objects as I wish without having to create a new canvas for each of them. I want two waterfalls with different colors but it doesn't work. I can't figure out why and I'm on it since a few hours. How can I make both red and blue waterfalls appear where the first has a lower z index than the last instantiation?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var w = canvas.width = window.innerWidth;
var h = canvas.height = window.innerHeight;
function waterfall(color) {
var self = this;
this.color = color;
this.water = [];
this.Construct = function(y, vel, acc) {
this.y = y;
this.vel = vel;
this.acc = acc;
}
for(var i = 0; i < 1000; i++) {
this.water.push(new this.Construct(Math.random() * 65, 0.1 + Math.random() * 4.3, 0));
}
this.flow = function(color) {
ctx.clearRect(0, 0, w, h);
for(var i = 0; i < this.water.length; i++) {
this.water[i].vel += this.water[i].acc;
this.water[i].y += this.water[i].vel;
ctx.beginPath();
ctx.arc(0 + i * 0.5, this.water[i].y, 2, 0, Math.PI * 2, false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
for(var i = 0; i < this.water.length; i++) {
if(this.water[i].y > window.innerHeight) {
this.water[i].y = 0;
}
}
requestAnimationFrame(function() {
self.flow.call(self);
});
}
this.flow(this.color)
}
new waterfall("blue");
new waterfall("red");
Here's my working code: https://jsfiddle.net/testopia/d9jb08xb/5/
and here again my intention to create two separate waterfalls but this time with the prototype inheritance:
https://jsfiddle.net/testopia/d9jb08xb/8/
I do prefer the latter but I just cant get either working.
The problem is that you are clearing the canvas in each waterfall. One is overpainting the other. You can immediately see that by commenting out the line
ctx.clearRect(0, 0, w, h);
Of course the water smears that way.
You have to manage your waterfalls in a way that in each animation frame you first clear the canvas then let them paint all.
Here is a quick attempt using a master flow_all() function:
https://jsfiddle.net/kpomzs83/
Simply move this line...
ctx.clearRect(0, 0, w, h);
... to here...
requestAnimationFrame(function() {
ctx.clearRect(0, 0, w, h); // ensure that w and h are available here.
self.flow.call(self);
});
This ensures that you do not clear the canvas before the 2nd waterfall is drawn. This clears the canvas, then draws the two waterfalls. Make sure you've added them to your water array, of course.

Javascript canvas draw from array

I am currently creating a family tree and have run into some problems when creating the children nodes coming from the father node. At the moment I am drawing topPerson.draw(context); which = the father node and then calling a for loop to cycle through an array of children they have which exists in the Partnership.js file, the array is this.mChildren = new Array();
What I am trying to do is cycle through the array and draw each child underneath the parent node in the same style as the parent (bordered with rectangle, image centered and name underneath).
The Person.js which is used to set the origin of canvas to center, draw a rectangle, write text including name of the node and then add node image:
Person.prototype.draw = function (context) {
//draw rectangle
var c = document.getElementById("canvas");
var context = c.getContext("2d");
context.scale(1, 1);
context.rect(canvas.width * 0.5, canvas.height * 0.5,160,210);
context.fillStyle = '#FFFFFF';
context.fill();
context.stroke();
context.fillStyle = '#000000';
context.font = "30px Arial";
context.fillText(this.getName(), canvas.width * 0.5 + 15, canvas.height * 0.5 + 190);
//get image and draw
context.drawImage(this.getImage(), canvas.width * 0.5 + 5, canvas.height * 0.5 + 5);
I have tried to create an array that looks like this:
for (i = 0; < mChildren.length; i++){
img = new Image();
img.src = mChildren[i];
img.onLoad = (function(img, i){
return function () {
context.drawImage(img, i*img.width, i*img.height);
}
})(img, i)
}

How to rendering Socket data in canvas html5?

1) How to rendering Socket data in canvas html5?
Using constant data i rending canvas.
When i am getting data from socket that is not rending like above one
1) socket data coming like same above example every 10 seconds
I think; your data array should be outside of 'drawWave' method as your fiddle ex and you should call 'drawWave' method just once in 'socket.on'. After a call of 'drawWave'. you should change your data array at 'socket.on' , not at 'drawWave'.
Could you try that?
var data = [];
var drawWaveCaught=false;
socket.on('canvasData', function (incomeData) {
console.log(incomeData);
data = JSON.parse("[" + incomeData + "]");
if(!drawWaveCaught){
drawWaveCaught = true;
that.drawWave();
}
});
function drawWave() {
requestAnimFrame(drawWave);
var n = 0;
var canvas = document.getElementById('canvas');
//alert(id);
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#dbbd7a";
ctx.fill();
ctx.lineWidth = "2";
ctx.strokeStyle = 'green';
// Drawing code goes here
for(n=1;n<=data.length;n++)
{
ctx.beginPath();
ctx.moveTo(n - 1, data[n - 1] * 2);
ctx.lineTo(n, data[n] * 2);
ctx.stroke();
ctx.clearRect(n + 1, 0, 10, canvas.height);
}
}

Categories