Javascript error in rails - javascript

i start to learn javascript with easy game tutorial http://www.youtube.com/watch?v=U7anheKJSaIand on RoR got error in index.html.erb:
<script>
var ctx, canvas;
var data;
window.onload = function main(){
canvas = document.createElement("canvas");
canvas.width = canvas.height = 200;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
init();
tick();
}
function init(){
data = new Tile(20,20);
}
function tick(){
window.requestAnimationFrame(tick);
update();
render();
}
function update(){}
function render(){
data.draw(ctx);
}
function Tile(x,y){
var x = x, y = y;
var tile = Tile.BlANK;
if(tile == null){
var _c = document.createElement("canvas");
_c.width = _c.height = 100;
_ctx = _c.getContext("2d");
_ctx.fillStyle = "skyblue";
//blank
_ctx.fillRect(0,0,100,100);
Tile.BlANK = new Image();
Tile.BLANK.src = _c.toDataURL();
tile = Tile.BLANK;
}
this.update = function(){}
this.draw = function(ctx){
ctx.drawImage(tile, x, y);
}
}
</script>
and this is error:
Tile.BLANK.src = _c.toDataURL();
Uncaught TypeError: Cannot set property src of undefined

Your error is here
Tile.BlANK = new Image();
It should be:
Tile.BLANK = new Image();
The error comes from .BlANK and it's because there is a typo. The l (L) is lowecase, and therefore later when you are trying to access the .src in you can't, because the real .BLANK is still undefined.
This is in function Tile(x,y){...}, but you also have the typo some other places. Just check your code for lowercase letters in .BLANK.

Related

Images not rendering randomly on canvas

Image of the bug is appearing only at one place i.e. x = 0,y = 0.
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
var bugSmashed = 0;
//rendering background image
function renderImage()
{
var backImage = new Image();
backImage.src = "jungle.jpg"
backImage.onload = function(){
c.drawImage(backImage,0,0,canvas.width,canvas.height)}
}
renderImage();
//Making a bug
class Bug {
constructor(x,y){
this.x = x;
this.y = y;
}
renderBug(){
var bugImage = new Image();
bugImage.src = "bug.png";
bugImage.onload = function(){
c.drawImage(bugImage,this.x,this.y,65,65)}}
}
Trying to make the bug appear randomly on the canvas
var interval = setInterval(function(){
var x = 32+Math.random()*(canvas.width-64);
var y = 32+Math.random()*(canvas.height-64);
var aBug = new Bug(x,y);
aBug.renderBug();}, 2000);
I am sure I am missing something. Any help is appreciated. Thanks
I found your problem: this changes its meaning inside a function. So when you use:
function(){c.drawImage(bugImage,this.x,this.y,65,65)}
this no longer refers to aBug! (It will instead refer to the global Window object.) You can use fat-arrow syntax instead (which preserves this):
() => c.drawImage(bugImage,this.x,this.y,65,65)
Another really ugly way which I discourage you from using is by creating a new reference to this, and then using that reference in your function:
let that = this;
function(){ c.drawImage(bugImage, that.x, that.y, 65, 65); };
Or you can simplify your code to have it gloss over onload logic, allowing you to avoid wrapping c.drawImage in a function in the first place (note the square which appears is a publicly addressable image):
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
//Making a bug
let bugImg = new Image();
bugImg.src = "https://th.bing.com/th/id/OIP.pXD0MAw4LeAcVrt3qRiEfwAAAA?pid=ImgDet&rs=1";
class Bug {
constructor(x,y){
this.x = x;
this.y = y;
}
renderBug(){
c.drawImage(bugImg, this.x, this.y, 65, 65);
}
}
var interval = setInterval(function(){
var x = 32 + Math.random()* (canvas.width - 64);
var y = 32 + Math.random()* (canvas.height - 64);
var aBug = new Bug(x, y);
aBug.renderBug();
}, 500);
<canvas id="canvas" width="100" height="100"></canvas>

bind(this) and requestAnimationFrame

After reading some solutions, I came up with this:
class Car{
constructor(carTag, throttle, yPosition){
this.carTag = carTag
this.carTag = new Image()
this.throttle = throttle
this.yPosition = yPosition
}
//Animate method that will animate cars across the screen
animate(){
const ref = this;
requestAnimationFrame(function(){
ref.animate();
});
const canvas = document.getElementById("gameboard");
const ctx = canvas.getContext("2d");
let xPosition = canvas.width;
setTimeout (function(){
ctx.clearRect(0, 0, xPosition, ref.yPosition);
ctx.drawImage(ref.carTag, xPosition, ref.yPosition);
xPosition -= 4;
console.log(xPosition);
}, 1000/ref.throttle);
}
}
const cars = new Car;
cars.carTag.src = "http://i.stack.imgur.com/Rk0DW.png";
cars.throttle = 2000;
cars.yPosition = 0;
cars.animate();
The problem I am still stumped on is why my car image is stuck in one position and not animating. Why is bind(this) interfering with requestAnimationFrame?
update: The latest version of this method doesn't produce error messages. But for some reason, the xPosition isn't updated which moves the car image left. I tried putting requestAnimationFrame to the bottom of the method, same result.
I found the solution. Thanks everyone!
class Car{
constructor(carTag, throttle, yPosition, xPosition, canvas, ctx){
//carTag property
this.carTag = carTag
this.carTag = new Image()
//throttle property
this.throttle = throttle
//yPosition property
this.yPosition = yPosition
//canvas, ctx property connecting with DOM
this.canvas = canvas
this.canvas = document.getElementById("gameboard");
this.ctx = ctx;
this.ctx = this.canvas.getContext("2d");
//xPosition property
this.xPosition = xPosition
this.xPosition = this.canvas.width;
}
//Animate method that will animate cars across the screen
animate(){
const ref = this;
setTimeout (function(){
ref.canvas.width = ref.canvas.width;
ref.ctx.drawImage(ref.carTag, ref.xPosition, ref.yPosition);
ref.xPosition -= 4;
requestAnimationFrame(function(){
ref.animate();
});
}, 1000/ref.throttle);
}
}
const cars = new Car;
cars.carTag.src = "http://i.stack.imgur.com/Rk0DW.png";
cars.throttle = 2000;
cars.yPosition = 0;
cars.animate();

HTML 5 canvas DrawImage only working after refresh

I have an issue with drawing to the canvas, I have an array of image information that i loop through and create image objects from. On each images onload event i draw it to the canvas, however this will only work after a refresh (once the images are in the cache it seems).
Here is a snippet from my code
var image = new Image();
image.src = img.src; //got from elsewhere, need to draw a background image first
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
img.parentNode.replaceChild(canvas, img);
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, canvas.width, canvas.height);
context.globalCompositeOperation = 'source-over';
//looping through my image info
for (var index in anaglyphs){
var anaglyph = anaglyphs[index];
if (anaglyph === undefined) continue;
//If x, y, height and width values are set in Image then set in mask
//otherwise use defaults
var x = 0;
if (anaglyph.x !== undefined) x = anaglyph.x;
var y = 0;
if (anaglyph.y !== undefined) y = anaglyph.y;
var width = canvas.width;
if (anaglyph.width !== undefined) width = anaglyph.width;
var height = canvas.height;
if (anaglyph.height !== undefined) height = anaglyph.height;
var alpha = new Image();
//Use of an intimidate function to stop javascripts closure
//overriding the variables before the onload event fired. Creating
//temporary variables in the intimidate function, which executes
//immediately, and storing the desired values inside them for callback.
(function (){
var xPos = x;
var yPos = y;
var maskWidth = width;
var maskHeight = height;
alpha.onload = function () {
context.drawImage(this, xPos, yPos, maskHeight, maskWidth);
};
})();
alpha.src = "data:"+anaglyph.content+";base64,"+encode64(anaglyph.data);
}
};
After a refresh it works fine and it will continue to work fine if I open the webpage using that script again, however it will fail again if I clear the cache and reopen the page. It only needs to work in the latest version of Firefox.
Thanks
Try putting alpha.src inside your closure:
(function (anaglyph,x,y,width,height){
var xPos = x;
var yPos = y;
var maskWidth = width;
var maskHeight = height;
alpha.onload = function () {
context.drawImage(this, xPos, yPos, maskHeight, maskWidth);
};
alpha.src = "data:"+anaglyph.content+";base64,"+encode64(anaglyph.data);
})(anaglyph,x,y,width,height);
BTW, why use a closure?
How about just a simple image loader with callback instead (just an example):
// callback -- after all images are loaded
function draw(images){
// or whatever you want in your callback
context.drawImage(images.image1, 10, 10, 50,50 );
context.drawImage(images.image2, 10, 100, 50,50);
}
var images = {};
var URLs = {
image1: 'ship.jpg',
image2: 'houseicon.png'
};
LoadImages(URLs, draw );
function LoadImages(URLs, callback) {
var loaded = 0;
var needed = 0;
for(var url in URLs) { needed++; }
for(var url in URLs) {
images[url] = new Image();
images[url].onload = function() {
if(++loaded >= numImages) {
callback(images);
}
};
images[url].src = URLs[url];
}
}

Javascript array and object/classes

i am trying to display three playing cards on the screen and for some reason everytime i run the code a type error appears and i have tried everything to try to fix it but nothing has worked. I think that the problem is in the array/object constructor but i think that everything is right inside of those.
"use strict";
function main(){
var cvs = document.getElementById("foo");
var ctx = foo.getContext("2d");
function Card(posX, posY, imgX, imgY){
this.posX = posX;
this.posY = posY;
this.imgX = imgX;
this.imgY = imgY;
this.width = 97;
this.height = 129;
}
Card.img = new Image();
Card.img.src = "allcards.png";
var cards = [new Card(0,0,0,0), new Card(400,400,194,258), new Card(200,200,291,387)];
var greaterX = false;
var lessX = false;
var greaterY = false;
var lessY = false;
var offsetX;
var offsetY;
setInterval(draw, 10);
function draw(){
ctx.fillStyle="rgb(0,255,255)";
ctx.clearRect(0,0,600,600);
ctx.drawImage(Card.img,cards[1].imgX,cards[1].imgY,Card.width,Card.height,cards[1].posX, cards[1].posY);
ctx.drawImage(Card.img,cards[2].imgX,cards[2].imgY,Card.width,Card.height,cards[2].posX, cards[2].posY);
}
}
var ctx = foo.getContext("2d");
should this not be
var ctx = cvs.getContext("2d");
You seem to have confused the static properties of the Card function object with those of the Card instances - the width and height properties are instance properties.
var cvs = document.getElementById("foo");
var ctx = cvs.getContext("2d");
function Card(posX, posY, imgX, imgY){
this.posX = posX;
this.posY = posY;
this.imgX = imgX;
this.imgY = imgY;
}
// default values/methods, accessible and overwritable on all instances:
Card.prototype.width = 97;
Card.prototype.height = 129;
Card.prototype.draw = function() {
ctx.drawImage(Card.img, this.imgX, this.imgY, this.width, this.height, this.posX, this.posY);
};
// static property:
Card.img = new Image();
Card.img.src = "allcards.png";
Card.img.onload = draw;
var cards = [new Card(0,0,0,0), new Card(400,400,194,258), new Card(200,200,291,387)];
function draw(){
ctx.fillStyle="rgb(0,255,255)";
ctx.clearRect(0,0,600,600);
for (var i=0; i<2; i++)
cards[i].draw();
};

javascript / canvas5 error from simple code

Error: uncaught exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMCanvasRenderingContext2D.drawImage]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://127.0.11.1/test/canvas5_b.php :: setup :: line 27" data: no]
function setup() {
var e = document.getElementById("mycanvas");
var ctx = e.getContext('2d');
var meter = new Image();
meter.src = "meter.jpg";
var meter_bar = new Image();
meter_bar.src = "meter_bar.jpg";
//alert(meter);
ctx.beginPath();/////////LINE 27////////////
ctx.drawImage(meter, 50, 100);
//ctx.globalCompositeOperation = "lighter";
ctx.drawImage(meter_bar, 68, 123);
ctx.closePath();
}
window.onload = setup;
Both the images are in the right folder. The thing that gets me is that it works if you put a alert(meter); before line 27. Its as if it is not loaded, but I have it running on window.onload, so I dont see how that is.
edit : It is an issue of when the image is loaded (ty rob). It appears best to globally declare and set the image src, and then call window.onload = setup, like this : (correct me if this is bad)
var img1, img2;
img1 = new Image();
img2 = new Image();
//declare and set the images src
img1.src = "meter.jpg";
img2.src = "meter_bar.jpg";
var canvasHeight, canvasWidth;
canvasHeight = 300;
canvasWidth= 600;
var ctx;
function setup() {
var e = document.getElementById("mycanvas");
ctx = e.getContext('2d');
draw();
}
function draw() {
ctx.clearRect(0,0,canvasWidth, canvasHeight);
ctx.beginPath();
ctx.drawImage(img1, 50, 100);
ctx.drawImage(img2, 68, 123);
ctx.closePath();
}
window.onload = setup;
Make sure the images are loaded first. For instance:
var img = new Image();
img.onload = function(){
ctx.drawImage(img,0,0);
}
// put this after onload, otherwise onload may
// not be called if image is in cache
img.src = 'whatev.png';
It's likely that the delay introduced by alert is enough to allow the image to load, but without alert, the images have not loaded in time. Try drawing the images onto the canvas only once they have loaded:
function setup() {
function maybeDraw() {
this.loaded = true;
if(meter.loaded && meter_bar.loaded) {
ctx.beginPath();
ctx.drawImage(meter, 50, 100);
//ctx.globalCompositeOperation = "lighter";
ctx.drawImage(meter_bar, 68, 123);
ctx.closePath();
}
}
var e = document.getElementById("mycanvas");
var ctx = e.getContext('2d');
var meter = new Image();
var meter_bar = new Image();
meter.onload = maybeDraw;
meter_bar.onload = maybeDraw;
meter.src = "meter.jpg";
meter_bar.src = "meter_bar.jpg";
}
window.onload = setup;

Categories

Resources