I get the error Uncaught TypeError: Cannot read property 'getContext' of null and the important parts in files are... I am wondering since game.js is in a directory below, it cannot find canvas? What should I do?
./index.html:
<canvas id="canvas" width="640" height="480"></canvas>
./javascript/game.js:
var Grid = function(width, height) {
...
this.draw = function() {
var canvas = document.getElementById("canvas");
if(canvas.getContext) {
var context = canvas.getContext("2d");
for(var i = 0; i < width; i++) {
for(var j = 0; j < height; j++) {
if(isLive(i, j)) {
context.fillStyle = "lightblue";
}
else {
context.fillStyle = "yellowgreen";
}
context.fillRect(i*15, j*15, 14, 14);
}
}
}
}
}
I guess the problem is your js runs before the html is loaded.
If you are using jquery, you can use the document ready function to wrap your code:
$(function() {
var Grid = function(width, height) {
// codes...
}
});
Or simply put your js after the <canvas>.
Put your JavaScript code after your tag <canvas></canvas>
You don't have to include JQuery.
In the index.html:
<canvas id="canvas" width="640" height="480"></canvas><script src="javascript/game.js">
This should work without JQuery...
Edit: You should put the script tag IN the body tag...
You should put javascript tag in your html file.
because browser load your webpage according to html flow, you should put your javascript file<script src="javascript/game.js"> after the <canvas>element tag. otherwise,if you put your javascript in the header of html.Browser load script first but it doesn't find the canvas. So your canvas doesn't work.
Write code in this manner ...
<canvas id="canvas" width="640" height="480"></canvas>
<script>
var Grid = function(width, height) {
...
this.draw = function() {
var canvas = document.getElementById("canvas");
if(canvas.getContext) {
var context = canvas.getContext("2d");
for(var i = 0; i < width; i++) {
for(var j = 0; j < height; j++) {
if(isLive(i, j)) {
context.fillStyle = "lightblue";
}
else {
context.fillStyle = "yellowgreen";
}
context.fillRect(i*15, j*15, 14, 14);
}
}
}
}
}
First write canvas tag and then write script tag. And write script tag in body.
You just need to put<script src='./javascript/game.js'></script> after your <canvas>.
Because the browser don't find your javascript file before the canvas
I assume you have your JS file declared inside the <head> tag so it keeps it consistent, like standard, then in your JS make sure the canvas initialization is after the page is loaded:
window.onload = function () {
var myCanvas = document.getElementById('canvas');
var ctx = myCanvas.getContext('2d');
}
There is no need to use jQuery just to initialize a canvas, it's very evident most of the programmers all around the world use it unnecessarily and the accepted answer is a probe of that.
This might seem like overkill, but if in another case you were trying to load a canvas from js (like I am doing), you could use a setInterval function and an if statement to constantly check if the canvas has loaded.
//set up the interval
var thisInterval = setInterval(function{
//this if statment checks if the id "thisCanvas" is linked to something
if(document.getElementById("thisCanvas") != null){
//do what you want
//clearInterval() will remove the interval if you have given your interval a name.
clearInterval(thisInterval)
}
//the 500 means that you will loop through this every 500 milliseconds (1/2 a second)
},500)
(In this example the canvas I am trying to load has an id of "thisCanvas")
Related
I'm developing a printing tool using HTML5 canvas. As a test, I've tried to draw an image and a rectangle on the canvas, and then copy it to a new window for printing, using the code below. But all I'm getting in the new window is a blank page.
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<canvas id="pageCanvas"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("pageCanvas");
canvas.height="700";
canvas.width="1000";
var ctx = canvas.getContext("2d");
var imageData="data:image/png;base64,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";
var imageObj = new Image();
imageObj.src = imageData;
imageObj.addEventListener("load", function() {
ctx.drawImage(imageObj, 50, 100,1000,600);
ctx.beginPath();
ctx.rect(100, 101, 200, 100);
ctx.lineWidth = 7;
ctx.strokeStyle = 'black';
ctx.stroke();
}, false);
var printWindow = window.open('');
printWindow.document.write('<html><BODY>');
printWindow.document.write('<center>');
printWindow.document.write('<img src="' + canvas.toDataURL()+'"/>');
printWindow.document.write('</center></body></html>');
printWindow.document.close();
printWindow.print();
</script>
</body>
</html>
Can you please guide me to overcome this issue?
You're opening the new window and trying to copy the content of the canvas onto it immediately after attaching the load event handler to the image, before the handler has actually had a chance to execute.
Just move all the JS code starting with the var printWindow = window.open(''); line inside the event handler, and it should work.
Oh, and please indent your code, especially if you expect anyone else to read it.
Addendum: If you want to wait until multiple images have loaded, the simplest way is to count the load events and call a function when all of them have fired, like this:
var imageURLs = [ ... image URLs here ... ];
var imageObjs = [];
var imagesLoaded = 0;
for (var i = 0; i < imageURLs.length; i++) {
var image = new Image();
image.addEventListener( "load", function() {
imagesLoaded++;
if (imagesLoaded == imageURLs.length) allImagesLoaded();
} );
image.src = imageURLs[i];
imageObjs.push(image);
}
function allImagesLoaded() {
// now do something with imageObjs
};
You could also get fancy and play with things like ES6 promises, but ultimately, the end result is the same.
See also:
Can I sync up multiple image onload calls?
Javascript - wait images to be loaded
I've tried everything I can think of and I'm reaching my wit's end.
"tilesheet.png" should be drawn onto the canvas but nothing I try seems to work.
Occasionally, when I try some new method I found online, it will appear to work fine once, but if I refresh the page it stops again.
Here is the code I'm using:
<head>
<title>Test Code</title>
<script src='scripts/jquery.js'></script>
</head>
<body>
<img id='img' src='images/tilesheet.png' style='position:absolute; visibility:hidden;'/>
<div id="port"></div>
<script>
viewHeight = 10;
viewWidth = 10;
$("#port").append("<canvas id='mapview' width='"+(viewWidth*32)+"' height='"+(viewHeight*32)+"' style='border:1px solid black;'>Your browser doesn't support the canvas element.</canvas>");
var worldMap = new gameMap(viewHeight,viewWidth);
worldMap.redraw();
// These functions define a gameMap "CLASS" //
function gameMap (height,width){
this.tileSheet = $("#img");
this.canvas = $("#mapview");
this.ctx = this.canvas.getContext("2d");//<-- Error is referring to this line
}
//Draw Function
gameMap.prototype.redraw = function(){
this.tileSheet.onload = function(){
this.ctx.drawImage(this.tileSheet,10,10);
}
this.tileSheet.src = "apps/gamejournal/images/tilesheet.png";
for(i = this.viewY; i < this.viewY+this.viewHeight; i++){
for(j = this.viewX; j < this.viewX+this.viewWidth; j++){
}
}
this.mapcss();
};
//CSS
gameMap.prototype.mapcss = function(){
var h = this.viewHeight*this.tileSize;
var w = this.viewHeight*this.tileSize;
$('#port').css({
"height":h,
"width":w,
"position":"relative",
"margin":"0 auto"
});
};
</script>
</body>
Update 10/30/15 - After using Google Chrome's "Inspect Element" feature, I've noticed that an error is being reported:
TypeError: this.canvas.getContext is not a function (test.php:26)
Does anyone know what might be causing this?
Update 11/4/15 - I've created a JSFiddle so you can see what my code is doing.
https://jsfiddle.net/6ss8ygLd/3/
Any help would be greatly appreciated. Thanks!
Okay, after a lot of extra research I seem to have found the solution to my own problem.
The problems proved to be a mix of using jquery in places where it wouldn't work, and putting my "onload" function in the wrong place.
Here is the final code I used:
<head>
<title>Test Code</title>
<script src='scripts/jquery.js'></script>
</head>
<body>
<img id="tiles" src="images/tilesheet.png" style="position:absolute; left:-9999px;"/>
<div id="port"></div>
<script>
viewHeight = 10;
viewWidth = 10;
var mapw = viewWidth*32;
var maph = viewHeight*32;
$("#port").append("<canvas id='mapview' width='"+mapw+"' height='"+maph+"' style='border:1px solid black;'>Your browser doesn't support the canvas element.</canvas>");
// These functions define a gameMap "CLASS" //
function gameMap (height,width){
this.canvas = document.getElementById("mapview");
this.ctx = this.canvas.getContext("2d");
this.tileSheet = document.getElementById("tiles");
}
//Draw Function
gameMap.prototype.redraw = function(){
this.ctx.drawImage(this.tileSheet,0,0);
};
//Call Functions
document.getElementById("tiles").onload = function(){
var worldMap = new gameMap(viewHeight,viewWidth);
worldMap.redraw();
}
</script>
</body>
I have a Image and I want to paint on top of it some square. But I keep getting undefined function on getContext('2d'). I must add that the var img is an image which is already loaded on the page, I'm trying to interpret it as a canvas since I am using another script which lets to select areas on the image and if I use a canvas the script will not work. So in the case where I can not interpret a image as a canvas what would you suggest?
Js function
function drawInput(dx1,dy1,dx2,dy2) {
var img = document.getElementById('home:tempImg');
var canvas = img;
console.log(canvas);
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, dx1, dy1,dx2-dx1,dy2-dy1);
};
imageObj.src = 'images/selected.png';
}
HTML
<h:body>
<h:form onsubmit="#{getComponents.getAllComponents()}" id="home">
<div>
<p:graphicImage id="tempImg" rendered="true" value="#{imageView.selectedImg}">
</p:graphicImage>
</div>
</h:form>
</h:body>
<script type="text/javascript">
var myJSONStr ='{ "area" : #{areaInputView.areaListString}}';
console.log(myJSONStr);
var json = JSON.parse(myJSONStr);
//console.log(json.area[1].x1);
for(var i=0;myJSONStr.length >i ; i++) {
console.log(json.area[i].x1, json.area[i].y1, json.area[i].x2, json.area[i].y2);
drawInput(json.area[i].x1, json.area[i].y1, json.area[i].x2, json.area[i].y2);
};
</script>
</html>
By leveraging custom JS 'classes' (of the type app.Image in this case), we can build a pretty neat wrapper that allows us to draw images dynamically based on other instances we have kept track of.
Check out this Codepen for a working example.
window.app = window.app || {};
app.Canvas = document.getElementById('myCanvas').getContext('2d');
app.Image = function(source, x, y) {
this.x = x;
this.y = y;
this.data = new Image();
this.data.addEventListener('load', this.draw.bind(this));
this.data.src = source;
};
app.Image.prototype.draw = function() {
app.Canvas.drawImage(this.data, this.x, this.y);
};
app.Image.prototype.getImageBounds = function() {
return {
height: this.data.height,
width: this.data.width
}
};
var myImage = new app.Image('http://placehold.it/250x250', 10, 10);
var mySecondImage = new app.Image('http://placesheen.com/100/100', myImage.x + 10, myImage.y + 10);
The most important line is the last one. Notice how we're initializing a new app.Image with x and y coordinates relative to the first image. By using a custom wrapper class that keeps track of this information, we're able to easily access the necessary data that we need in a variety of circumstances.
I hope this helps to get you on the right track! Let me know if you have any questions about the code, and I'll be glad to explain.
I'm learning javascript, so a coworker is having me do basic animation in the browser. I just finished my code, using the canvas element to display images to the screen, but nothing happens when I run the code. My debug statements don't get printed to the console, nor do any errors. Can anyone see a problem with my code?
<html>
<body>
<canvas id="console" width="600" height="600"></canvas>
<script type="text/javascript">
(function() {
console.log("at top of script");
var ballImage = new Image();
ballImage.src = "http://upload.wikimedia.org/wikipedia/en/e/ec/Soccer_ball.svg";
var time_stamp;
var balls[];
var BALL_COUNT = 2;
function requestAnimFrame (cb) {
function fallback (cb){
window.setTimeout(cb, 10);
}
var func = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
fallback;
func (cb);
}
function update() {
var ts = Date.now();
var time_elapsed = ts - (time_stamp || ts);
time_stamp = ts;
canvas = document.getElementById("canvas");
// update ball positions and detect wall collisions
balls.forEach(function (ball){
canvas.clearRect( ball.xLocation, ball.yLocation, ball.scaleWidth, ball.scaleHeight );
ball.update(time_elapsed);
canvas.drawImage( ball.image, ball.xLocation, ball.yLocation, ball.scaleWidth, ball.scaleHeight );
});
}
function programRun() {
update();
requestAnimationFrame(programRun);
}
/*
CLASS: ball
*/
function Ball() {
// all the code and functions for the ball class....
}
ballImage.onload = function() {
// fill up the array containing the ball objects
for (var i = 0; i < BALL_COUNT; ++i){
balls.push (new Ball ("ball" + i));
}
// start running the program
programRun();
};
console.log("got to end of script");
}) ();
<script>
</body>
</html>
I'm almost certain it's some basic thing I messed up, because I didn't get any errors back from running the code. Any help is appreciated :)
This line caused it..
var balls[];
correct it by replacing it with:
var balls = [];
you should see the logs then.
Update:
I created a fiddle with the code above and revised some fragments of your code to conform to a version that may suit your needs in writing your own version of the ball animation.
The following are the problems that I saw in your code:
Of course the array declaration mentioned above var balls[]; to var balls = [];
Don't forget to declare variables with the var keyword. I changed
time_stamp = ts;
canvas = document.getElementById("canvas");
to
var time_stamp = ts;
var canvas = document.getElementById("canvas");
3. Your html code suggests that the ID of the canvas is id="console" but your javascript tries to get an element with id="canvas".
Changed
<canvas id="console" width="600" height="600"></canvas>
to
<canvas id="canvas" width="600" height="600"></canvas>
Inside your ball.each() iteration uses the canvas element to invoke methods that are supposed to be within the CanvasRenderingContext2D.
Add something after your var canvas declaration.
var ctx = canvas.getContext('2d');
use the ctx variable to manipulate the canvas itself. This should be your function update() definition.
function update() {
var ts = Date.now();
var time_elapsed = ts - (time_stamp || ts);
var time_stamp = ts;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
// update ball positions and detect wall collisions
balls.forEach(function (ball){
ctx.clearRect( ball.xLocation, ball.yLocation, ball.scaleWidth, ball.scaleHeight );
ball.update();
ctx.drawImage( ballImage, ball.xLocation, ball.yLocation, ball.scaleWidth, ball.scaleHeight );
});
}
UPDATE:
Always use var when declaring variables. If you want to use them as a variable that can be accessed from different scopes(inner scopes) then you can do it by declaring them a scope higher.
Something like this:
function BallAnimation() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
function updateBall() {
ctx.fillRect(.....);
...
}
function Ball() {
this.canvas = canvas;
}
}
In such a manner you can still obtain the reference of the variables that you want to share from other scopes. Read this article to know more why vars are important.
Here's my code. I created a VIBGOYR pattern on the canvas and want to change the radial gradient of the system after a time interval so that it looks animated.
function activate(index){
canvas =document.getElementById("exp");
context = canvas.getContext('2d');
//Start.
draw(index);
//Functions.
function draw(index){
drawGradiantSq(index);
var t=setTimeout(doTimer,1000);
}
function doTimer(){
draw(index+10);
}
function drawGradiantSq(fi){
console.log(fi);
var g1 = context.createRadialGradient(0,300,0,500,300,fi);
colors = ["violet","indigo","blue","green","orange","yellow","red"];
var x= 1/12;
for (var i=0;i<colors.length;i++){
g1.addColorStop(i*x,colors[i]);
}
context.fillStyle = g1;
context.fillRect(0,0,500,600);
var g2 = context.createRadialGradient(1000,300,0,500,300,fi);
for (var i=0;i<colors.length;i++){
g2.addColorStop(i*x,colors[i]);
}
context.fillStyle = g2;
context.fillRect(500,0,1000,600);
}
}
But the output i'm getting only changes the gradient only once although the timer seems to be working fine.
The HTML file:
<body>
<canvas id="exp" width="1000px" height="600px"></canvas>
<button onclick="activate(index+=10);">Paint</button>
</body>
The variable index is a global variable set to 0.
Try using setInterval instead of setTimeout.
setTimeout is only triggered once:
'setInterval' vs 'setTimeout'