Javascript canvas animating - javascript

I want to make a loading bar for my web application and I want to use a html canvas for this. This is the script that I use to fill up the canvas:
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
var xPos = 0;
draw = function() {
if(xPos < 300){
c.rect(0, 0, xPos, 30);
c.fill(255,0,0);
xPos += 0.5;
}
};
</script>
I tested this code on a online code converter (khan academy) and it worked (of course without the first 2 lines and c. in front of most things), and that is also my trouble I don't know where I have to put c. in front of?
I simplified the page a little bit:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000"
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
</script>
</body>
</html>

Whatever you are trying to draw... this:
draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
... it is a definition of variable in global context (context of window object), then assigning a function to it. That's all - it only defines the behavior.
What you need also needs to execute that (a sidenote: to execute it after the canvas is actually created - when you put code in a script tag after canvas tag - it's sufficient and you did it already).
To execute the function use:
draw();
Or don't wrap code in function at all (unless it's to be called multiple times).
Or use a syntax construct to execute the function created in place like this:
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15); // use this to achieve animation effect
}
})();
var xPos = 0;
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#FF0000";
var draw;
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15);
}
})();
#bar {
width: 300px;
height: 50px;
}
<canvas id="bar"></canvas>
Edit: I've been thinking of what you might need, as it's not entirely abvious what you want. I have created this jsfiddle. Maybe it'll be of any help.

Hmmm...
You got some things mixed up. Try this:
<html>
<canvas id = "cvs1" width = "300" height = "30"></canvas>
</html>
And for the script:
var c = document.getElementById("cvs1").getContext("2d");
c.fillStyle = "#ff0000" //Set Fill Color(Set to red)
if(xPos < 300){
c.fillRect(xPos, 0, 30, 30);
xPos += 0.5;
}
If not:
What you did was use fill and rect seperately. You need to set the color, and then use the fillRect() function to draw the rectangle.
EDIT: You got the x,y,width,height as width,height,x,y. Fixed answer.
Good luck!

You need to call draw for every animation step. You could do this using setTimeout, setInterval or requestAnimationFrame :
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000";
xPos=0;
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
requestAnimationFrame(draw);
}
};
requestAnimationFrame(draw);
</script>
</body>
</html>

Related

Can't display canvas object

Guys Here is a function which should display a red ball on the frame, but it isn't doing so, I am watching a tutorial to do that, I am doing everything exactly as he does but I can't figure out what is the problem here.. Please I need to know this. If somebody can understand please help..
var canvas,ctx,w,h,game=true;
var ball;
var BALL = function(x,y){
this.x = x;
this.y = y;
this.color = "red";
this.radius = 10;
this.vx = 3;
this.vy = -4;
}
window.onload = init;
function init() {
canvas = document.getElementById("canvas");
w = canvas.width;
h = canvas.height;
ctx = canvas.getContext('2d');
ball = new BALL(w/2,h/2+50);
beginGame();
}
function beginGame(){
if(game){
ctx.clearRect(0,0,w,h);
ball.x+=ball.vx;
ball.y+=ball.vy;
if((ball.x+ball.radius)+ball.vx>w || (ball.x-ball.radius)+ball.vx<0){
ball.vx = -ball.vx;
}
ctx.fillStyle = ball.color;
ctx.beginPath();
ctx.arc(ball.x,ball.y,ball.radus,0,2*Math.PI,true);
ctx.closePath();
ctx.fill();
window.requestAnimationFrame(beginGame);
}else{
//Game Over
}
}// End of beginGame function
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>არკანოიდი</title>
<script src='tools.js'></script>
<script src='jquery-1.11.2.min.js' language='javascript' > </script>
<style>
canvas {
border: 1px solid silver;
}
</style>
</head>
<canvas id="canvas" width="800" height="600"></canvas>
<body>
</body>
</html>
I don' know if it will fix everything but your canvas is outside of your body tags.
for script tags:
1. don't use language='javascript'. this is not needed.
2. If you do want to explicitly declare it as javascript, then use type="text/javascript". This is automatically the case, so you don't even need to do that.
3. Put the canvas inside the body tags.
4. use window.addEventListener("load", init) instead of window.onload(init)
5.inside startgame function:
function beginGame()
{
// previous lines omitted...
ball = new BALL(x, y);
// other lines here...
}

Drawing and saving an image as JPEG in HTML Canvas

I am creating an app which allows user to draw a digit(using mouse) in Canvas. When they click on submit, the image should be saved as a JPEG and Clear should Erase the digit drawn in canvas. I am new to HTML5 Canvas. I saw some tutorials which created a canvas, but I am unable to save and clear canvas. Any help would really be appreciated. Thanks.
Here is my HTML:
<div style="padding-bottom: 20px;padding-left: 210px;">
<div class="btn-group" role="group" aria-label="...">
<button type="button" id="save" class="btn btn-default">Submit</button>
<button type="button" id="clear" class="btn btn-default">Clear</button>
</div></div>
</div>
Javascript within Script tag:
var clear = document.getElementById('clear');
clear.addEventListener('click', clearCanvas);
var clearCanvas = function(e) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, 500, 400);
ctx.clearRect(20, 20, 100, 50);
}
The tutorial you're using fails to mention a few key things:
The canvasInAPerfectWorldline isn't used: you can delete it.
You need jQuery: just add <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script/> in your <head> section.
You should wrap your javascript in the jQuery boilerplate, to ensure it gets executed after the rest to the document has loaded: $( document ).ready(function() { <your javascript here> });
The canvasWidth and canvasHeight variables are never set: add this line before the variables are used:var canvasWidth = 600; var cavasHeight = 400;
The variables mouseX and mouseY are never used: you can delete them (but take a look at the onClick() function two lines later to see what they would have been used for).
The finished result should look like this:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Create HTML5 Canvas JavaScript Drawing App Example</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<style>canvas { border: 1px solid #ccc; }</style>
<script type="text/javascript">
$( document ).ready(function() {
var canvasWidth = 600; var cavasHeight = 400;
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', cavasHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
context = canvas.getContext("2d");
$('#canvas').mousedown(function(e){
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#canvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#canvas').mouseup(function(e){
paint = false;
});
$('#canvas').mouseleave(function(e){
paint = false;
});
$('#clear').click(function(){
clickX.length = 0;
clickY.length = 0;
clickDrag.length = 0;
redraw();
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function redraw(){
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
});
</script>
</head>
<body>
<div id="canvasDiv"></div>
</body>
</html>
As for saving your canvas as a JPEG, that's more complicated. As markE has pointed out, there's a related question here which shows one way to do it.
EDIT: Adding a 'Clear' button:
Your 'drawing' is really just a series of pen movements stored in the clickX, clickY and clickDrag arrays. Each time redraw() is called, the drawing gets recreated from the arrays. So just drawing a white rectangle will only clear the screen until the next redraw(). Instead, you can clear the arrays by adding this to your javascript:
$('#clear').click(function(){
clickX.length = 0;
clickY.length = 0;
clickDrag.length = 0;
redraw();
});
(BTW by deleting the details of your original question, you make it hard for the next person to understand the context of the answers. You should either (a) add to your original question, or (b) ask a new question. Also you can upvote and/or accept any answers you find helpful. Thanks)
I think that's a duplicated question. See here
Can I get image from canvas element and use it in img src tag?
var image = new Image();
image.id = "pic"
image.src = canvas.toDataURL();
document.getElementById('image_for_crop').appendChild(image);

Ecg graph with html5 canvas

My need is to draw a ECG graph on canvas for socket data per every data iteration.
I tried to look into several graph plugins which use canvas to plot graphs, tried http://www.flotcharts.org/ but didn't succeed.
I Tried to plot graph using below basic html5 canvas drawline with sample data.
var fps = 60;
var n = 1;
drawWave();
function drawWave() {
setTimeout(function() {
requestAnimationFrame(drawWave2);
ctx.lineWidth = "2";
ctx.strokeStyle = 'green';
// Drawing code goes here
n += 1;
if (n >= data.length) {
n = 1;
}
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);
}, 1000 / fps);
}
But it is not giving me the exact graph view as attached image. I'm not able to understand how to achieve graph like ecg graph. Please help me to get rid of this problem.
The characteristics with an ECG is that is plots the signal horizontally headed by a blank gap. When the end of the right side is reached is returns to left side and overdraw the existing graph.
DEMO
Setup
var ctx = demo.getContext('2d'),
w = demo.width,
h = demo.height,
/// plot x and y, old plot x and y, speed and scan bar width
speed = 3,
px = 0, opx = 0,
py = h * 0.8, opy = py,
scanBarWidth = 20;
ctx.strokeStyle = '#00bd00';
ctx.lineWidth = 3;
/// for demo we use mouse as signal input source
demo.onmousemove = function(e) {
var r = demo.getBoundingClientRect();
py = e.clientY - r.top;
}
loop();
The main loop:
The loop will plot whatever the signal amplitude is at any moment. You can inject a sinus or some other signal or read from an actual sensor over Web socket etc.
function loop() {
/// move forward at defined speed
px += speed;
/// clear ahead (scan bar)
ctx.clearRect(px,0, scanBarWidth, h);
/// draw line from old plot point to new
ctx.beginPath();
ctx.moveTo(opx, opy);
ctx.lineTo(px, py);
ctx.stroke();
/// update old plot point
opx = px;
opy = py;
/// check if edge is reached and reset position
if (opx > w) {
px = opx = -speed;
}
requestAnimationFrame(loop);
}
To inject a value simply update py (outside loop).
It would be far more helpful, if you included an image of what it does produce, rather than stating that it doesn't do that. Anyhow, it looks like you're only drawing a single line per frame. You need to run a loop with lineTo inside, iterating through all values of n.
Something along the lines of the below except from a sound-synthesizer. Just pay attention to the fact that there's a drawing-loop. In my case, there are often 40,000 or 50,000 samples that need to be drawn on a canvas of only a few hundred pixels wide. It seems like redundant drawing in my case, but doing th intuitive thing, of a single point per pixel results in an inaccurate image. The output of this looks something (88200 samples per 1024 pixels)
function drawFloatArray(samples, canvas)
{
var i, n = samples.length;
var dur = (n / 44100 * 1000)>>0;
canvas.title = 'Duration: ' + dur / 1000.0 + 's';
var width=canvas.width,height=canvas.height;
var ctx = canvas.getContext('2d');
ctx.strokeStyle = 'yellow';
ctx.fillStyle = '#303030';
ctx.fillRect(0,0,width,height);
ctx.moveTo(0,height/2);
ctx.beginPath();
for (i=0; i<n; i++)
{
x = (i*width) / n;
y = (samples[i]*height/2)+height/2;
ctx.lineTo(x, y);
}
ctx.stroke();
ctx.closePath();
}
Since your live data is streaming non-stop, you need a plan to deal with a graph that overflows the canvas.
Here's one solution that pans the canvas to always show only the most recent data.
Demo: http://jsfiddle.net/m1erickson/f5sT4/
Here's starting code illustrating this solution:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// capture incoming socket data in an array
var data=[];
// TESTING: fill data with some test values
for(var i=0;i<5000;i++){
data.push(Math.sin(i/10)*70+100);
}
// x is your most recent data-point in data[]
var x=0;
// panAtX is how far the plot will go rightward on the canvas
// until the canvas is panned
var panAtX=250;
var continueAnimation=true;
animate();
function animate(){
if(x>data.length-1){return;}
if(continueAnimation){
requestAnimationFrame(animate);
}
if(x++<panAtX){
ctx.fillRect(x,data[x],1,1);
}else{
ctx.clearRect(0,0,canvas.width,canvas.height);
// plot data[] from x-PanAtX to x
for(var xx=0;xx<panAtX;xx++){
var y=data[x-panAtX+xx];
ctx.fillRect(xx,y,1,1)
}
}
}
$("#stop").click(function(){continueAnimation=false;});
}); // end $(function(){});
</script>
</head>
<body>
<button id="stop">Stop</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
I think this web component is both prettier and easier to use. It using canvas as a backend of draw. If you going use it all you need to do is call bang() on every appearing beat
document.body.innerHTML += '<ecg-line></ecg-line>';
ecgLine((bang) => setInterval(() => bang(), 1000));
Do you mean something like this?
var canvas = document.getElementById("dm_graphs");
var ctx = canvas.getContext("2d");
ls = 0;
d = 7; // sesitivity
function updateFancyGraphs() {
var gh = canvas.height;
var gh2 = gh / 2;
ctx.drawImage(canvas, -1, 0);
ctx.fillRect(graphX, 0, 1, canvas.height);
var size = Math.max(-gh, Math.min((3 * (Math.random() * 10 - 5)) * d, gh));
ctx.beginPath();
ctx.moveTo(graphX - 1, gh2 + ls / 2);
ctx.lineTo(graphX, gh2 + size / 2);
ctx.stroke();
ls = size;
}
function resizeCanvas() {
var w = window.innerWidth || document.body.offsetWidth;
canvas.width = w / 1.5;
canvas.height = window.innerHeight / 1.5;
graphX = canvas.width - 1;
ctx.lineWidth = 1; // 1.75 is nicer looking but loses a lot of information.
ctx.strokeStyle = "Lime";
ctx.fillStyle = "black";
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
z = setInterval(() => updateFancyGraphs(), 20)
body {
min-height: 100ev;
}
body,
html,
canvas {
font: 15px sans-serif;
height: 100hv;
width: 100%;
margin: 0;
padding: 0;
background: #113355;
color: white;
overflow: hidden;
}
#dm_status,
footer {
text-align: center;
}
#dm_graphs {
image-rendering: optimizeSpeed;
background: rgba(0, 0, 0, 0.7);
}
<html>
<head>
<title>Zibri's Graph</title>
<meta name="viewport" content="width=device-width">
</head>
<body>
<canvas id="dm_graphs"></canvas>
</body>
</html>

canvas animation javascript functions and global variables

Please, may someone help me! I am new in javascript.
I want to make canvas animation using javascript. But I have the following error
SCRIPT5007: Unable to get value of the property 'getContext': object
is null or undefined drawing_script.js, line 31 character 5
Here is the code.
Javascript:
// JScript source code
/*
Because the canvas can hold only one context at time, we'll create two canvas. Each one with its context.
One canvas for the circle, and another one for the square.
*/
var canvasCircle;
var contextCircle;
var x = 400;
var y = 300;
var dx = 2;
var WIDTH = 800;
var HEIGHT = 600;
// the circle wont make any transsformation.
function draw_circle(x, y, r) {
contextCircle.beginPath();
contextCircle.arc(x, y, r, 0, 2 * Math.PI, true);
contextCircle.closePath();
contextCircle.stroke();
}
function clear_canvas() {
contextCircle.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
//canvasCircle = document.getElementById("canvas_circle");
canvasCircle = document.getElementById("canvas_circle");
contextCircle = canvasCircle.getContext('2d');
return setInterval(draw, 10);
}
function draw() {
// clear_canvas();
draw_circle(x, y, 50);
// if (x + dx > WIDTH || x + dx < 0)
// dx = -dx;
// x += dx;
}
init();
HTML5:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<script type="text/javascript" src="Scripts/drawing_script.js" language="javascript"></script>
<title>Blackberry</title>
</head>
<body>
<div class="drawing" style="background:Green">
<canvas id="canvas_circle" width="800" height="600"></canvas>
This is happening because your executing the script before you create the canvas.
Create the canvas element FIRST then embed the javascript.
IE: canvasCircle is undefined because you can't get an element by ID that does not exist yet!
I found the answer: the init() should be
function init() {
s_canvas = document.getElementById("canvas_square");
// Check if the canvas is supported and if the getContext is available
if (s_canvas && s_canvas.getContext) {
s_context = s_canvas.getContext("2d");
return setInterval(draw, 10);
}
else {
alert("Canvas is not supported!");
}
}
And the called of init() is replace with window.onload=init.
Since you said that you are new to javascript, I believe that the problem could be that the browser on which you are running the code may not be supporting canvas.

Performance of RaphaelJS with thousands of paths/rectangles

I really only care about Webkit, but in general, is Raphael JS expected to perform well when building thousands of rectangles?
Additionally, I would need to be able to handle events on each of these rectangles (yipes).
I've got a C++ solution which works but I'd rather use RaphaelJS.
Thanks :)
I don't know nothing about RaphaelJS but I can give you a performance hint with this code:
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title></title>
<script>
window.onload = function () {
var rectangles = 5000;
for (var i = 0; i < rectangles; i ++) {
var height = 50;
var width = 50;
var canvas = document.createElement ("canvas");
canvas.height = height;
canvas.style.margin = "15px";
canvas.width = width;
canvas.addEventListener ("click", function () {
alert ("You like to MOVE !");
}, false);
var ctx = canvas.getContext ("2d");
ctx.fillStyle = "silver";
ctx.fillRect (0, 0, width, height)
document.body.appendChild (canvas);
}
canvas = document.body.getElementsByTagName ("canvas");
window.setInterval (function () {
for (var i = 0; i < canvas.length; i ++) {
canvas[i].style.margin = (Math.floor (Math.random () * 16)) + "px";
}
}, 100);
}
</script>
</head>
<body></body>
</html>
5000 rectangles moving around with "onclick" event:
If you would like to test out performance of Raphael JS I've posted a quick example of plotting 10,000 points. Tests render and clear times.
http://jsfiddle.net/jaRhY/1049/

Categories

Resources