I'm programming a game
I have the next settings:
HTML game.html
<canvas id="canvas" width="288" height="512"></canvas>
<script src="game.js"></script>
JAVASCRIPT game.js
var document;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//load images
var pipeNorth = new Image();
pipeNorth.src = "images/pipeNorth.png";
function draw(){
/*code */
alert(pipeNorth.height);
requestAnimationFrame(draw);
}
draw();
PROBLEM
If I set an alert displaying the image height, it shows 0 during the first two or three alerts, then it starts showing the real height.
Why does this happen? How do I fix this? I think it means the image is not fully loaded when the game begins?
From my experience this happens because the document rendering takes some time. My technique for this case is a time delay:
function draw(){
var delay = 200;//Your delay in milliseconds
setTimeout(function(){
/*code */
alert(pipeNorth.height);
requestAnimationFrame(draw);
},delay);
}
Is it usable for you?
Yes you are right the image is not fully loaded when the game begins.to fix this you simply have to use the "load" event :
var document;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//load images
var pipeNorth = new Image();
pipeNorth.src = "images/pipeNorth.png";
function draw(){
/*code */
alert(pipeNorth.height);
requestAnimationFrame(draw);
}
pipeNorth.addEventListener("load",function(){
//this function will execute when the image is fully loaded
draw();
});
Related
I am learning html canvas and below is my html code.
<!DOCTYPE html>
<html>
<head>
<script language="javascript">
function moveImage(x) {
var context = document.getElementById('myCanvas').getContext("2d");
var img = new Image();
img.onload = function () {
context.drawImage(img, x, 259);
}
img.src = "flower.jpg";
}
function startDrawing() {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(50, 300);
context.lineTo(950, 300);
context.stroke();
var x=50;
setInterval(function() {
x = x+20;
moveImage(x);
}, 1000);
}
</script>
</head>
<body onload="startDrawing()">
<canvas id="myCanvas" width="1000" height="1000">
</body>
</html>
Please find the below output from this code:
How can I remove the traces of 'older frames' (of the flower), as you could see lots of flowers while it is moving from left to right in the screen shot ? Please help the code changes required.
Thanks.
The problem is you aren't clearing the canvas before drawing on it again. You can clear it using clearRect.
setInterval(function() {
// Clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
x += 20;
moveImage(x);
}, 1000);
Keep in mind that this will clear the entire canvas. If you're rendering anything else, you'll want to redraw it after the clear.
You need to re-render the frame. Here's some code from an incomplete game I wrote:
var main = function () {
var now = Date.now(),
delta = now - then;
update(delta / 1000);
render();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
GitHub repo code
My render function contains the context.drawImg() work (getting properly re-rendered), and that's similar to your moveImage function.
Edit: A little explanation. The image traces are previous renderings of the your image at each updated position. Without the frame itself being reset, each move of the image is preserved on the screen, giving the appearance of a trail of images.
I've been losing my mind over this. I spent 3 hours trying different methods and finding a solution online, and I still haven't fixed it.
I have two separate images(not a spritesheet) and they need to be displayed one after the other, as an animation, infinitely. Here's is my latest code:
var canvas, context, imageOne, imageTwo, animation;
function init(){
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
imageOne = new Image();
imageTwo = new Image();
imageOne.src = "catone.png";
imageTwo.src = "cattwo.png";
// Just to make sure both images are loaded
setTimeout(function() { requestAnimationFrame(main);}, 3000);
}
function main(){
animation = {
clearCanvas: function(){
context.clearRect(0, 0, canvas.width, canvas.height);
},
renderImageOne: function(){
context.drawImage(imageOne, 100, 100);
},
renderImageTwo: function(){
context.drawImage(imageTwo, 100, 100);
}
};
animation.renderImageOne();
// I also tried calling animation.clearCanvas();
context.clearRect(0, 0, canvas.width, canvas.height);
animation.renderImageTwo();
// I put this here to confirm that the browser has entered the function, and that it hasn't stopped after animation.renderImageTwo();
console.log("cats");
requestAnimationFrame(main);
}
init();
But the problem is that the only one image is displayed, and it's not moving. I can't see any errors or warnings in the console. I'm also sure HTML and JavaScript are connected properly and the images are in the right path. So in any case, only the image in the first function is displayed. Example: animation.renderImageOne(); displays catone, but if I replace it with animation.renderImageTwo(); it displays cattwo.
The problem is here:
animation.renderImageOne();
// I also tried calling animation.clearCanvas();
context.clearRect(0, 0, canvas.width, canvas.height);
animation.renderImageTwo();
Is it's drawing the first image, clearing the canvas, then drawing the second image, then after all that it draws to the screen. Leaving you with only seeing the second image. You will need a variable that alternates values, and use that to determine which picture you should draw:
var canvas, context, imageOne, imageTwo, animation;
var imageToDraw = "one";
And then:
function main() {
...
if(imageToDraw == "one") {
animation.renderImageOne();
imageToDraw = "two";
}
else if(imageToDraw == "two") {
animation.renderImageTwo();
imageToDraw = "one";
}
...
}
Note: You don't need to define animation inside main(), you can move it into global scope. That way you don't redefine it each time you call main().
I'm looking to draw an image onto a canvas for my HTML page using a separate Javascript file. The HTML I have thus far is fine, my problem seems to lie within the script. This is what I have currently:
function doFirst(){
var x = document.getElementById('canvas');
canvas = x.getContext('2d');
var pic = new image();
pic.src="http://i1273.photobucket.com/albums/y418/Cloudtwonj/Backgroundtest_zps2a6a6b51.jpeg";
pic.addEventListener("load", function(){canvas.drawImage(pic,0,0,x.width,x.height)}, false);
}
window.addEventListener("load", doFirst, false);
Can anyone tell me what I might have done wrong or forgot?
The constructor is Image, not image - capitalization matters!
var pic = new Image();
function doFirst() {
var x = document.getElementById('canvas');
canvas = x.getContext('2d');
var pic = new Image();
pic.src = "http://i1273.photobucket.com/albums/y418/Cloudtwonj/Backgroundtest_zps2a6a6b51.jpeg";
pic.addEventListener("load", function() {
canvas.drawImage(pic, 0, 0, x.width, x.height)
}, false);
}
window.addEventListener("load", doFirst, false);
<canvas id="canvas"></canvas>
I have:
<canvas id='canvas' width="300" height="409" style="border:2px solid darkblue" >
</canvas>
And then:
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src = 'http://4.bp.blogspot.com/...-21+Kingfisher.JPG';
alert(image.src);
context.drawImage(image, 0, 0, 300, 400);
</script>
In IE 10, the image is painted as "to be expected". However, when I remove that alert statement, the picture is not painted!
In Chrome, no image is painted on my local PC, whether with or without the alert statement.
What could be happening? The fiddle is here
That is because loading images is an asynchronous operation. The alert call helps the browser to wait a bit so the image loading can finish. Therefor the image will be available at drawImage that follows.
The correct way to implement this is to use the code this way:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var image = new Image(); //document.createElement('img'); for Chrome due to issue
// add a onload handler that gets called when image is ready
image.onload = function () {
context.drawImage(this, 0, 0, 300, 400);
}
// set source last so onload gets properly initialized
image.src = 'http://4.bp.blogspot.com/...-21+Kingfisher.JPG';
The draw operation inside the callback for onload could just as easily have been a function call:
image.onload = nextStep;
// ...
function nextStep() {
/// draw image and other things...
}
I'm playing with the canvas element in HTML5 and I have noticed a peculiar behavior. On initial load, an image I'm displaying does not show. However, when I refresh the browser, it displays appropriately. I've used IE9 and Chrome. Both behave identically. The JavaScript code looks like this:
window.onload = load;
function load() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.fillRect(0, 0, 640, 400);
var image = new Image();
image.src = "Images/smiley.png";
context.drawImage(image, 50, 50);
}
The rectangle draws correctly both times, it's the smiley that only shows on a browser refresh.
I'm in the process of learning HTML5 and JavaScript. I'm sure I'm just doing something stupid, but I can't figure it out.
Images load asynchronously, so only after refresh it loads early enough because it's cached. Normally it isn't loaded yet at the time you call drawImage. Use onload:
var image = new Image();
image.src = "Images/smiley.png";
image.onload = function() {
context.drawImage(image, 50, 50);
};
This happened with me as well (only for IE9 for me) anyways, i found a simple solution.
Set the background of the canvas to the initial image you wish to display.
var canvas = document.getElementById("canvas");
canvas.style.background="url('image.png')";
That should work!
Actually, even just using image.onload = function() {}, you can still run into problems. Do use this technique (that's not at all what I'm saying), but move it to the bottom of your page.
As an example, I have a social networking site that uses canvas to show the profile photo (URI stored to the DB), and print it to canvas, then overlay a logo.
<section id="content">
<article id="personalbox" >
<h2>Hi! My name is {profile_name}</h2>
<a id="friendbutton" href=""><img src="views/default/images/friend.png" width="12" height="12" /><span>Add {profile_name} as a friend?</span></a>
<video id="profilevideo" width="240" height="144">DEBUG: Video is not supported.</video>
<canvas id="profilecanvas" width="240" height="144" >DEBUG: Canvas is not supported.</canvas>
<a id="gallerytextlink" href="gallery.html" >Click to visit {profile_name} Gallery</a>
<table id="profileinfotable1">
...
</section>
<script type="text/javascript">
function init() {
var cvs = document.getElementById("profilecanvas");
var ctx = cvs.getContext("2d");
var img = new Image();
img.src = "uploads/profile/{profile_photo}";
img.onload = function() {
// Ignore. I was playing with the photo.
ctx.drawImage(img, 42, 32, 186, 130, cvs.width/2 - (186-42)/2, cvs.height/2 - (130-32)/2, 186-42, 130-32);
drawLogo(cvs,ctx);
}
}
function drawLogo(cvs,ctx) {
var logo = "Enter Logo Here.";
ctx.fillStyle = "rgba(36,36,36,0.6)";
ctx.strokeStyle = "rgba(255,255,255,0.3)";
ctx.font = "bold italic 6pt Serif";
ctx.textAlign = "left";
ctx.textBaseline = "middle" ;
ctx.save();
ctx.strokeText(logo, 4, cvs.height-11);
ctx.strokeText(logo, 6, cvs.height-11);
ctx.strokeText(logo, 4, cvs.height-9);
ctx.strokeText(logo, 6, cvs.height-9);
ctx.fillText(logo, 5, cvs.height-10);
ctx.restore();
}
window.onload = init;
</script>
Ideally, this would go all the way at the bottom before the end </body> tag, but I put it up higher because of my template system. Apparently, this gives the image time to load after the canvas element has been drawn to the screen and is ready to receive input.
I can't rely on setting the background of the canvas, and I have no desire to contend with refreshes. For whatever reason, just including the script with img.onload = function() {} was not enough. Move it lower, and save yourself the headaches.