I am new to javascript and I'm learning about it. While doing so I encountered this problem which I can't figure out and I'm here for your help.
This is the page that I was on, http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_canvas_empty
Now I when I run the following on the console(firebug) it returned null.
document.getElementById("myCanvas");
Why I'm I not getting the expected result here?
The DOM has already been loaded when the draw-function is called, that is correct.
But the var canvas = document.getElementById('control');-line is evaluated before that, because it is not in the draw-function. It is executed immediately in the of the document BEFORE the elements have been rendered.
I would suggest you change your init function to something like that
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
Related
I use a very simple piece of code (but then obviously with my image instead of Image.png). I am trying to give my canvas a background image.
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img = new Image();
img.onload=start;
img.src="Image.png";
function start(){
ctx.drawImage(img,0,0);
}
But I receive this error:
ERROR: 'Image' is not defined. [no-undef] about the part:
var img = new Image().
I tried to replace this with
var img = document.createElement("img");
Then the error is gone, but nothing displays, no image whatsoever, its just empty.
Has anybody any idea what I am doing wrong?
Thanks in advance!
FULL CODE
var document;
var ctx;
var window;
window.onload = function () {
start();
}
function start(){
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.src="image.png";
img.onload=start;
function start(){
ctx.drawImage(img,0,0,400,400);
}
}
You need to attach the image you have created to the DOM.
document.getElementById("image-container").appendChild(img);
Edit: I apologize, I see you are drawing it to a canvas object. In that case I would suspect that your image is failing to load properly.
A couple ideas: you could add some debugging output within the start() function or set a breakpoint, then look at what the 'img' contains at that point in time. Or you could check the status code on the 'Network' tab of the devtools console. Or you could replace the image with one that is known to work, such as www.google.com/images/logo.png. This all should hepl you narrow down the issue.
Note: window is a global variable so you shouldn't declare it, and names that are properties of window such as window.document are also globals - can be referenced as document without declaring it. Occasionally JS frameworks complain, but there are framework-specific ways to solve this. Duplicate declaration of these variables is not a good path to go down.
If you're adding these in response to ESlint errors, you should add eslintrc.json to your project root (if you don't have it already), and give it the following property so it doesn't complain for browser globals:
{
"env": {
"browser": true
}
}
As to why Image is not defined, this would not happen on a modern browser environment. It has to be something with your environment setup. Is there any information you could provide about how you are running this code?
Try setting the onload callback before you set the image's src.
var img = document.createElement("img");
img.onload=start;
img.src="image.png";
If the image is cached, then onload would be fired as soon as src is set, i.e. before it is assigned to start see this question.
I had a little problem today and thought I could try stack overflow. I'll be short and sweet (I removed lot of code to make this clear).
I recently discovered raphaeljs and I like it.
I make some circle draggable and it works fine like this:
Working script:
<script>
var paper = Raphael(100,100,500,500);
var circ = paper.circle(50,50,10)
var start = function(){ };
var move = function(dx,dy)
{
this.attr({cx: this.ox + dx, cy: this.oy + dy});
};
var up = function(){};
circ.drag(move,start,up);
<script>
Ok fine, it works and all functions are called properly!
BUT!
I want my move ,start ,up functions to be inside an object and not in the main page
SO
here's my next code
<script src="myobject.js"></script>
<script>
var paper = Raphael(100,100,500,500);
var myobj = new myobject("12","12","6");
<script>
Content of myobject.js :
function myobject(vx,vy,vr)
{
var x,y,r;
x=vx;y=vy;r=vr
paper.circle(x,y,r);
var start = function(){};
var move = function(dx,dy){};
var up = function(){};
this.drag(move,start,up); // error here this line crash
}
I cannot find how to use the drag function inside my object to make it draggable.
Well, that's it. I hope I've been clear and pardon me if there's anything wrong with the way I made this post but it is my first one!
Thanks to everyone that will try to help me!
Wilson
Inside myobject, this variable points to this object, and not to Raphael circle. As myobject does not have drag function, the code yields an error. To make it work, you must refer to Raphael object that has to be dragged, i.e.
function myobject(vx,vy,vr) {
...
this.circle = paper.circle(x,y,r);
...
this.circle.drag(move,start,up);
...
}
Fine, #Hubert OG was right but I also had to change the way I declared my function from
var start()=function
to
this.start() = function
WARNING: Fill your circle/forms because if you don't you have to click the fine border to move it around.
I am new to oop in js. I'm working on a HTML5 game using Box2dWeb and I decided that I should it make it completely oop based. So I created a physics class like this in a separate file called physics.js
(function(window)
{
function Physics(element, scale){
//init world logic
}
Physics.prototype.debug = function(){
//debug draw logic
};
Physics.prototype.step = function(dt){
//step logic
};
//making this class(or object) visible on the global scope
//so i can create vars of this type anywhere in the application
window.Physics = Physics;
}(window));
Now I have a main game.js file where I init all my game physics, graphics, assets, etc. Here are the contents:
(function(){
function init(){
var physics = new Physics(document.getElementById("b2dCanvas"), 30);
console.log(physics);
physics.debug();
}
window.addEventListener("load", init);
}());
This file, initializes my Physics object without any problem. Ultimately this is what i want. Great! But, prior to this, the file was like this, without the init() function.
(function(){
var physics = new Physics(document.getElementById("b2dCanvas"), 30);
console.log(physics);
physics.debug();
}());
This apparently threw the error Uncaught TypeError: Cannot call method 'getContext' of null. This meant, the physics constructor was being called(and naturally element at this point was null) without me invoking it. How was that possible? My self-executing function in game.js should have initialized the Physics object right? What am I missing?
Your script was running before the HTML was fully parsed, and before your canvas element was added to the DOM. When you added window.addEventListener("load", init);, you made it run when the window.onload event was triggered. At that moment, the DOM was fully parsed.
In modern browsers, you could also replace that with
document.addEventListener("DOMContentLoaded", init);
That event will trigger when the DOM is ready, but doesn't wait for other resources like images (unlike onload).
Or, just add all your scripts just before closing the body tag. At that point, every HTML tag in the body will already have been inserted into the DOM.
This meant, the physics constructor was being called(and naturally
element at this point was null) without me invoking it. How was that
possible?
Becase you are calling it, using this syntax:
(function(){...}());
^^
call
That will call the function when the script is parsed as part of the normal page script parsing, and will not wait for the document/DOM to be ready for you to manipulate. You'll want to either use some sort of document 'load' listener, or remove that particular syntax and call the function manually when you're sure the DOM is ready.
My guess is that you're calling the function before the DOM is ready. Put the script include at the bottom of your code or even better just wrap all init a window load listener.
The error has nothing to do with the Physics object not being ready. It has to do with the code inside of it trying to reference an element that is not on the page when the code is called.
It is simple you were calling
document.getElementById("b2dCanvas")
before the element was loaded on the page. When getElementById does not find anything it returns null.
So what your code looks like if you were to inspect it
var physics = new Physics(null, 30);
and element is null
function Physics(element, scale){
var ctx = element.getContext("2d"); //<-- where the error occurs since element is null
Hence the error: Uncaught TypeError: Cannot call method 'getContext' of null.
When you listen for the load event, that means the element is there so it loads with no problem. Other way of dealing with it is to add the script to the bottom of the page.
I want to log 'tapped' and execute the HUD asap, but oauth_upload_photo is causing it to lag (apparently because of hoisting). How can I snap the HUD instantly??
var submit_post = function submit_post(){
console.log('tapped');
// Show HUD
plugins.navigationBar.hideRightButton();
var hud = document.getElementById("hud");
hud.style.display = 'block';
// Get the image
var image = document.getElementById('myImage');
var imageURI = image.src;
// Get the caption from the textarea
var cap = document.getElementById('tar');
var caption = cap.value;
// Call upload photo
oauth_upload_photo(imageURI,caption);
};
Your issue (which needs a lot more explanation before we could understand what you're actually asking about) has nothing to do with javascript variable hoisting. All hoisting does is cause variables to be defined at the top of the function,regardless of where their initial declaration is located in the function. It doesn't change the execution order of any statements.
Also, in some browsers console.log() is not guaranteed to be completely synchronous and the display of the data in the log window is not necessarily immediate either. There is sometimes a delay before it actually logs. I don't know if this is caused by marshalling data across process boundaries, general repaint logic or some other internal implementation issue.
You may also want to change this:
var submit_post = function submit_post(){
to this:
var submit_post = function (){
or even this:
function submit_post() {
so you aren't double defining the same symbol.
this may be an odd one to explain:
I want to create dynamically a collection of canvas that will have a single image in it. And this displays (after much hassle and getting rid of the onload event) but when I try to refresh the page I sometimees get nothing on the screen.
And when I was using thee onload event (to wait until the image is loaded) it would not display or display everything in the last canvas.
Here is a snippet of the code:
var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
img = new Image()
img.src = sources[i]
canvas = document.createElement('canvas')
$(canvas).attr('id', i)
canvas.height=300
canvas.width=200
var context = canvas.getContext('2d');
//onload commented out allows expected display
//img.onload = function() {
context.drawImage(img, 0, 0);
//}
divCanvas.appendChild(canvas)
}
I have seen many posts that seemed to look like mine and tried quite a few but to no avail.
I think the issue is that var context is overwritten before the img.onload event is triggered. The img.onload event only has a reference to global scope. This is why only the last image shows up. You need to find the correct context inside the event.
I can't test your code directly, but I think it should be something like this:
var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
img = new Image();
img.src = sources[i];
img.id = i; //Allow img to remember its corresponding canvas/context
canvas = document.createElement('canvas');
$(canvas).attr('id', i);
canvas.height=300;
canvas.width=200;
var context = canvas.getContext('2d');
divCanvas.appendChild(canvas);
img.onload = function() {
//Use the image id to get the correct context
var canvas = document.getElementById(this.id);
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
}
}
For consistent behavior, you must use onload. If you don't the canvas drawing code may execute before the image is loaded and the desired image will not be drawn.
It might be that the onloads that would draw to the other canvases are not being called because the Images are getting garbage collected before the event can fire.
Try adding
var images = [];
At the start of your code and
images.push(img);
After the img = new Image() line.
If that doesn't work, try adding those images to the DOM tree-- img.setAttribute('style', 'display: none') first so you don't see them and they don't interfere with the document structure.
I found the fix here:
https://developer.mozilla.org/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Drawing_images
Apparently they have dropped img.onload to have the function called when the body has finished loaded.
Though, I still do not understand why my script or, ellisbben solution was not working.
If anyone as an answer for it, it would be very welcomed...