I have the following HTML. It draws a Colorado state flag, but only if I move the lines that are in the window.onload() function into the drawLogo() function, so I think the trouble is not that drawLogo() doesn't get called, but that the global canvas, ctx, x, and y are somehown not really global. I want to put in other functions that do other things in this same canvas, so that is why I want the canvas, ctx, x, and y to be global.
I know window.onload() gets executed, because I can also get it to draw the flag by putting the call to drawLogo() inside window.onload().
<!DOCTYPE html>
<html lang="en">
<head>
<title>Logo</title>
<script type="text/javascript">
var canvas;
var ctx;
var x;
var y;
window.onload = function () {
canvas = document.getElementById('logo');
ctx = canvas.getContext('2d');
x = canvas.width;
y = canvas.height;
};
var drawLogo = function() {
var radius = 23;
var counterClockwise = false;
ctx.beginPath();
ctx.rect(3, 20, 75, 30);
ctx.fillStyle = 'rgba(0,0,255,0.8)';
ctx.fill();
ctx.beginPath();
//ctx.globalAlpha = 0.5;
ctx.rect(3, y-60, 75, 30);
ctx.fillStyle = 'rgba(0,0,255,0.8)';
ctx.fill();
ctx.beginPath();
ctx.arc(40, 70, 30, 0, 2 * Math.PI, counterClockwise);
ctx.fillStyle = 'Yellow';
ctx.fill();
ctx.beginPath();
ctx.arc(40, 70, 30, 2.15 * Math.PI, 3.85 * Math.PI, counterClockwise);
ctx.strokeStyle = '#cc3333';
ctx.lineWidth = 18;
ctx.stroke();
};
</script>
</head>
<body>
<div>
<canvas id="logo" width="600" height="150"></canvas>
<script type="text/javascript">
drawLogo();
</script>
</div>
</body>
</html>
window.onload is called when the entire page is loaded, this means CSS, JS files, Fonts, images and almost everything is downloaded.
Your drawLogo function instead is executed when the script tag is evaluated while loading the page.
What is happening then is that the drawLogo function is called before you populate the global variables.
A simple solution would be to put your drawLogo function inside the window.onload function.
I 'd also suggest to change the onload event with a quicker onready in your case, but it is a minor thing.
Related
I'm currently creating a simple program using HTML Canvas and Javascript. All that I need to happen is for a ball to be drawn at coordinates on the canvas and then move around using some velocity variables etc.
The issue is, I've created a Ball object as I intend to have multiple balls on screen at a time, however nothing is showing on my canvas.
I've read over this a few times, I'm receiving no errors so I'm struggling to figure out what's happening with this.
EDIT:
I've added a console log to check the drawSelf() is running, which it is but still no error/result
CODE
<!DOCTYPE html>
<html>
<head>
<title>Bouncing Ball</title>
</head>
<script>
var Date
var canvas;
var ctx;
var dx=5;
var dy=5;
function init(){
canvas = document.getElementById('game');
ctx = canvas.getContext('2d');
setInterval(draw,10);
console.log("Initialised: " + new Date());
}
function Ball(x, y, dx, dy){
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.drawSelf = function () {
ctx.beginPath();
ctx.fillStyle = "#4286f4";
ctx.arc(this.x,this.y,20,0,Math.PI*2,true);
ctx.closePath();
console.log("Ball is drawing self!");
if(this.x<0 || this.x>800){
dx=-dx;
}
if(this.y<0 || this.y>800){
dy=-dy;
}
this.x+=this.dx;
this.y+=this.dy;
}
this.getX = function () {
console.log("X:" + this.x);
console.log("Y:" + this.y);
}
}
//Creating Ball object.
let ball1 = new Ball(400, 400, 5, 5);
function draw(){
ball1.drawSelf();
}
</script>
<body onLoad="init()">
<div id="canvas-area">
<canvas id="game" width="800" height="800"></canvas>
</div>
</body>
<html>
You forgot to add ctx.stroke() or ctx.fill(), taken from the Mozilla docs
this.drawSelf = function () {
ctx.beginPath();
ctx.fillStyle = "#4286f4";
ctx.arc(this.x,this.y,20,0,Math.PI*2,true);
ctx.stroke();
ctx.closePath();
console.log("Ball is drawing self!");
if(this.x<0 || this.x>800){
dx=-dx;
}
if(this.y<0 || this.y>800){
dy=-dy;
}
this.x+=this.dx;
this.y+=this.dy;
}
Also sidenote, since you don't set the background every draw, your canvas will just add the ball to it's current state, resulting in a cool pattern, but something you probably don't want. To fix this, make this your draw method.
function draw(){
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ball1.drawSelf();
}
EDIT: Instead of using setInterval I recommend using requestAnimationFrame. You can read more about it here
// Main Javascript
//Variables to use
var canvas;
var context;
var ball;
canvas = documnet.getElementById("canvas");
context = canvas.getcontext("2d");
//Creates my ball function based off of what is on canvas for ball
ball = new Ball();
Well my ball is not showing up on screen and I am pretty sure I have done everything correctly but can someone look over it and find something I missed or made a mistake on? I really need some help and I appreciate the help!
I have two Javascript files in here because I have one for my main javascript and ball
//ball.js
function ball() {
//The ball itself
this.startAngle = 0;
this.endAngle = 360 * Math.PI * 2;
this.radius = 40;
this.drawBall = true;
//location for my ball
this.x = canvs / width / 2;
this.y = canvas / height / 2;
//coloring my ball
this.color = " #00FFFF";
//draw function
this.draw = function () {
context.fillStyle = this.color;
context.beginPath();
content.arc(this.x, this.y, this.redius, this.startAngle, this.Endangle, this.drawBall);
context.fill();
}
}
My HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" >
<title>Robert's Ball Game</title>
<link type="text/css" rel="stylesheet" href = css/robs.css" />
</head>
<body>
<canvas id="canvas" width="1000" height="720"></canvas>
</body>
//Javascript
<script type="text/javascript" src= "javas/ball.js"> </script>
<script type="text/javascript" src= "javas/rob.js"> </script>
</html>
You've got lots of spelling and capitalisation errors, and you hadn't actually called the ball.draw() function.
I've added comments in the code below to show what I've changed to make it work (click "run" to see the result):
var canvas;
var context;
var ball;
canvas = document.getElementById("canvas"); // "document", not "documnet"
context = canvas.getContext("2d"); // needs capital "C" in getContext
//Creates my ball function based off of what is on canvas for ball
ball = new Ball();
ball.draw(); // you didn't call .draw()
//ball.js
function Ball() {
//The ball itself
this.startAngle = 0;
this.endAngle = 360 * Math.PI * 2;
this.radius = 40;
this.drawBall = true;
//location for my ball
this.x = canvas.width / 2; // you had canvs / width / 2
this.y = canvas.height / 2; // you had canvas / height / 2
//coloring my ball
this.color = "#00FFFF";
//draw function
this.draw = function () {
context.fillStyle = this.color;
context.beginPath();
// on next line you had "content" instead of "context",
// and "Endangle" instead of "endAngle", and "redius" instead of "radius":
context.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle, this.drawBall);
context.fill();
}
}
<canvas id="canvas" width="200" height="200"></canvas>
I am trying to make to objects move towards each other in Canvas, when they meet and overlap one should then disappear and the other should fall down. Now I got the animation to do that, but one of the items is flickering.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<body onload="draw(530,15); draw1(1,15);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
function draw(x,y){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.clearRect(x, y, 600, 400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (x, y, 70, 50);
ctx.restore();
x -= 0.5;
if(x==300)
{
return;
};
var loopTimer = setTimeout('draw('+x+','+y+')',5);
};
function draw1(w,e){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.clearRect(w-1,e-2,600,400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (w, e, 70, 50);
ctx.restore();
w += 1;
if(w==265)
{
w -= 1;
e +=2;
};
var loopTimer = setTimeout('draw1('+w+','+e+')',10);
};
</script>
</body>
</html>
Been trying for two days, but can't seem to fix it properly. Thanks in advance.
You are rendering too many frames per second forcing the browser to present frames. Each time a draw function returns the browser presumes you want to present the frame to the page.
Animations need to be synced to the display refresh rate which for most devices is 60FPS. To do this you have one render loop that handles all the animation. You call this function via requestAnimationFrame (RAF) which ensures that the animation stays in sync with the display hardware and browser rendering.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<!-- dont need this <body onload="draw(530,15); draw1(1,15);">-->
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas,ctx,x,y,w,e;
var canvas,ctx,x,y,w,e;
function draw() {
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect(x, y, 70, 50);
};
function draw1(w, e) {
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect(w, e, 70, 50);
};
function update(time){ // high precision time passed by RAF when it calls this function
ctx.clearRect(0,0,canvas.width,canvas.height); // clear all of the canvas
if(w + 70 >= x){
e += 2;
}else{
x -= 0.75;
w += 1;
};
draw(x,y);
draw1(w,e);
requestAnimationFrame(update)
// at this point the function exits and the browser presents
// the canvas bitmap for display
}
function start(){ // set up
x = 530;
y = 15;
w = 1;
e = 15;
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
requestAnimationFrame(update)
}
window.addEventListener("load",start);
</script>
</body>
</html>
You're method of animation is very outdated (ie, the use of setTimeout). Instead you should be using requestAnimationFrame as demonstrated below. This will give smooth, flicker free animation.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<body onload="requestAnimationFrame(animate);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 530, y = 15;
function animate(){
requestID = requestAnimationFrame(animate);
ctx.clearRect(x, y, 600, 400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (x, y, 70, 50);
x -= 0.5;
if(x==300)
{
cancelAnimationFrame(requestID)
};
}
</script>
</body>
</html>
the first 2 parameters of ctx.clearReact in both draw functions should be 0:
ctx.clearRect(0, 0, 600, 400);
This means you clear all canvas.
I want to write a simple scrolling right to left starfield. I have printed out the stars randomly. Now, how do I target each star and randomly give it a speed (say 1-10) and begin moving it? I also need to put each star back on the right edge after it reaches the left edge.
Following is my code written so far:
<!DOCTYPE html>
<html>
<head>
<script>
function stars()
{
canvas = document.getElementById("can");
if(canvas.getContext)
{
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect (0, 0, 400, 400);
ctx.fill();
starfield();
}
}
//print random stars
function starfield()
{
for (i=0; i<10; i++)
{
var x = Math.floor(Math.random()*399);
var y = Math.floor(Math.random()*399);
var tempx = x;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
}
</script>
</head>
<body onload="stars()">
<h1>Stars</h1>
<canvas id="can" width="400" height="400"style="border:2px solid #000100" ></canvas>
</body >
</html>
Here's a quick demo on Codepen. After saving the stars in an array, I'm using requestAnimationFrame to run the drawing code and update the position on every frame.
function stars() {
canvas = document.getElementById("can");
console.log(canvas);
if (canvas.getContext) {
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect(0, 0, 400, 400);
ctx.fill();
starfield();
}
}
// Create random stars with random velocity.
var starList = []
function starfield() {
for (i = 0; i < 20; i++) {
var star = {
x: Math.floor(Math.random() * 399),
y: Math.floor(Math.random() * 399),
vx: Math.ceil(Math.random() * 10)
};
starList.push(star);
}
}
function run() {
// Register for the next frame
window.requestAnimationFrame(run);
// Reset the canvas
ctx.fillStyle = "black";
ctx.rect(0, 0, 400, 400);
ctx.fill();
// Update position and draw each star.
var star;
for(var i=0, j=starList.length; i<j; i++) {
star = starList[i];
star.x = (star.x - star.vx + 400) % 400;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(star.x, star.y, 3, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
stars();
run();
Put your x,y coordinates in an array, and then make a function that draws the array.
var stars = [
{x:110, y:80},
{x:120, y:20},
{x:130, y:60},
{x:140, y:40}
]
Then make a function to alter the x,y coordinates (for example increment y=y+1) each time before using the draw function.
Bonus:
This array solution allows you to have each star move at its own speed, you could store a delta (say 1 upto 3) in that array, and do y=y+delta instead. This looks 3D.
You could even go further and have a seperate x and y delta, and have stars fly out from the middle, which is even more 3D!
Or even simpler/faster could be to have the render function accept an x,y offset. It could then even wrap around, so that what falls off the screen on one side comes back on the other. It looks like you are rotating in space.
I simple way to imitate star movement towards a point(like a center) is simply divide both X and Y by Z coordinate.
nx = x / z
ny = y / z
And simply decrease z value as you iterate. As z is big, your points will be around a point and as z decreases the result will be bigger and bigger which imitates "moving" of a stars.
Just providing a solution which uses jQuery because using it you can get the output with lesser lines of code compared to complete canvas solution.It uses two canvas divs to get the desired output:
Check this fiddle
Little updated code from the code posted in the question
<script>
function stars(){
canvas = document.getElementById("can1");
canvasCopy = document.getElementById("can2");
if(canvas.getContext){
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect (0, 0, 400, 400);
ctx.fill();
starfield();
var destCtx = canvasCopy.getContext('2d');
destCtx.drawImage(canvas, 0, 0);
}
}
//print random stars
function starfield(){
for (i=0;i<10;i++){
var x = Math.floor(Math.random()*399);
var y = Math.floor(Math.random()*399);
var tempx = x;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
}
</script>
<body onload="stars()">
<h1>Stars</h1>
<div id="starBlocks">
<canvas id="can1" width="400" height="400"style="border:2px solid #000100" ></canvas>
<canvas id="can2" width="400" height="400"style="border:2px solid #000100" ></canvas>
</div>
</body >
jQuery
function playStars()
{
$('#starBlocks').animate({
scrollLeft : 400
},10000,'linear',function(){
$('#starBlocks').scrollLeft(0);
playStars();
});
}
playStars();
CSS
#starBlocks{
white-space:nowrap;
font-size:0px;
width:400px;
overflow:hidden;
}
I placed an text on html5 canvas object using fillText option, question is I need to move the text position or change the color of the text that is already rendered.
Shortly I need to know how to Manipulate particular child of canvas element
This will move a small circle over your canvas
var can = document.getElementById('canvas');
can.height = 1000; can.width = 1300;
var ctx = can.getContext('2d');
var x = 10, y = 100;
ctx.fillStyle = "black";
ctx.fillRect(700, 100, 100, 100);
function draw() {
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(250,0,0,0.4)';
ctx.fill();
x += 2;
ctx.fillStyle = "rgba(34,45,23,0.4)";
ctx.fillRect(0, 0, can.width, can.height);
requestAnimationFrame(draw);
//ctx.clearRect(0,0,can.width,can.height);
}
draw();
<canvas id="canvas" style="background:rgba(34,45,23,0.4)"></canvas>
I think there is no object model behind the canvas, so you cannot access a "child object" like a "text object" and change it.
What you can do is that you draw the text again with a different color that overwrites the "pixels" of the canvas.
If you want to move the text, first you have to either clear the canvas or re-draw the text with a background/transparent color to get rid of the text in the previous position. Then you can draw the text in the new position.
I've never tried it but I think this would be the way to do it.
var canvas = document.getElementById("canvas"); //get the canvas dom object
var ctx = canvas.getContext("2d"); //get the context
var c = { //create an object to draw
x:0, //x value
y:0, //y value
r:5; //radius
}
var redraw = function(){ // this function redraws the c object every frame (FPS)
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear the canvas
ctx.beginPath(); //start the path
ctx.arc(c.x, c.y, c.r, 0, Math.PI*2); //draw the circle
ctx.closePath(); //close the circle path
ctx.fill(); //fill the circle
requestAnimationFrame(redraw);//schedule this function to be run on the next frame
}
function move(){ // this function modifies the object
var decimal = Math.random() // this returns a float between 0.0 and 1.0
c.x = decimal * canvas.width; // mulitple the random decimal by the canvas width and height to get a random pixel in the canvas;
c.y = decimal * canvas.height;
}
redraw(); //start the animation
setInterval(move, 1000); // run the move function every second (1000 milliseconds)
Here is a fiddle for it.
http://jsfiddle.net/r4JPG/2/
If you want easing and translations, change the move method accordingly.
Hope it is allowed to advertise somebody's project.
Take a look at http://ocanvas.org/ you can get inspiration there.
It is object like canvas library. Allows you to handle events, make animations etc.
<html>
<head>
<title>Canvas Exam</title>
</head>
<body>
<canvas id="my_canvas" height="500" width="500" style="border:1px solid black">
</canvas>
<script>
var dom=document.getElementById("my_canvas");
var ctx=dom.getContext("2d");
var x1=setInterval(handler,1);
var x=50;
var y=50;
r=40;
function handler()
{
ctx.clearRect(0,0,500,500);
r1=(Math.PI/180)*0;
r2=(Math.PI/180)*360;
ctx.beginPath();
//x=x*Math.random();
x=x+2;
r=r+10*Math.random();
ctx.arc(x,y,r,r1,r2);
ctx.closePath();
ctx.fillStyle="blue";
ctx.fill();
ctx.stroke();
if(x>400)
{
x=50;
y=y+10;
}
r=40;
}
</script>
</body>
</html>