my EventListener are not working - javascript

What I'm trying to do is, if I hover over one of my drawn objects, I want to display a blurb saying which city it is, the population and an image of their downtown etc. as of right now i just trying yo get it to work. i also wondering if there something else i can you instead of alert, something that would make a bubble instead
<script>
function startCanvas() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//first circle
var one = c.getContext("2d");
//second circle
var two = c.getContext("2d");
//third cirle
var three = c.getContext("2d");
//fourth circle
var four = c.getContext("2d");
//fifth cirle
var five = c.getContext("2d");
// new image
var image = new Image();
image.onload = function () {
ctx.drawImage(image, 69, 50);
//draw a circle
one.beginPath();
one.arc(180, 90, 10, 0, Math.PI * 2, true);
one.closePath();
one.fill();
two.beginPath();
two.arc(155, 138, 10, 0, Math.PI * 2, true);
two.closePath();
two.fill();
three.beginPath();
three.arc(160, 180, 10, 0, Math.PI * 2, true);
three.closePath();
three.fill();
four.beginPath();
four.arc(257, 210, 10, 0, Math.PI * 2, true);
four.closePath();
four.fill();
five.beginPath();
five.arc(238, 235, 10, 0, Math.PI * 2, true);
five.closePath();
five.fill();
};
image.src = 'denmark.jpg';
//function hover over circle one, give alert
one.addEventListener('mouseover',
function (e) {
e = e || window.event;
alert('this is a test');
}
);
}
</script>
</head>
<body onload="startCanvas()">
<canvas id="myCanvas" width="600" height="600";">
Your browser does not support the HTML5 canvas tag.
</canvas>
</body>
</html>

Your code will throw this error
Object # < CanvasRenderingContext2D > has no method 'addEventListener'
So Modify this part
//function hover over circle one, give alert
one.addEventListener('mouseover',
function (e) {
e = e || window.event;
alert('this is a test');
}
);
by this code
//function hover over circle one, give alert
c.addEventListener('mouseover',
function (e) {
e = e || window.event;
alert('this is a test');
}
,false);
This Will Work;

Have you considered using a slightly higher-level drawing library, such as RaphaelJS? Or EaselJS?
I've messed around with both of these, and they make this kind of interactive canvas work much more elegant, and will also improve your cross-browser compatibility.

Related

Create shapes by for loop in canvas

EDIT:i will post all my code the html and js,and excuse me for too many comments
I am trying to create rectangles in canvas by for loop (there is input user)
and I want to access them in another function to do some stuff,
the main problem is how to access the shapes's name after loop I have tried this but when i call them in another function it gives me,
undefined "object name"
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = document.getElementById("myCanvas");
//drawing the base off the towers
var base_twr1 = c.getContext("2d");
base_twr1.beginPath();
base_twr1.moveTo(550, 500);
base_twr1.lineTo(300, 500);
base_twr1.lineWidth = 10;
base_twr1.strokeStyle = '#ff0000';
base_twr1.closePath();
base_twr1.stroke();
var base_twr2 = c.getContext("2d");
base_twr2.beginPath();
base_twr2.moveTo(900, 500);
base_twr2.lineTo(650, 500);
base_twr2.closePath();
base_twr2.stroke();
var base_twr3 = c.getContext("2d");
base_twr3.beginPath();
base_twr3.moveTo(1250, 500);
base_twr3.lineTo(1000, 500);
base_twr3.closePath();
base_twr3.stroke();
//drawing the towers
var twr1 = c.getContext("2d");
twr1.beginPath();
twr1.moveTo(430, 300);
twr1.lineTo(430, 500);
twr1.closePath();
twr1.stroke();
var twr2 = c.getContext("2d");
twr2.beginPath();
twr2.moveTo(780, 300);
twr2.lineTo(780, 500);
twr2.closePath();
twr2.stroke();
var twr3 = c.getContext("2d");
twr3.beginPath();
twr3.moveTo(1130, 300);
twr3.lineTo(1130, 500);
twr3.closePath();
twr3.stroke();
//array to know each tower what contains
//to avoid collisions
var disks_in_twrs = [];
var twr1_holder = [];
var twr2_holder = [];
var twr3_holder = [];
//start function check the user input
//and call another function if everthing
//is fine
function btn_start() {
disks_number = document.getElementById("disk_input").value;
disks_number = parseInt(disks_number);
if (disks_number > 0) {
if (disks_number < 8)
put_disks(disks_number);
} else
alert('write number');
}
var width_disks_start = 305;
var height_disks_start = 490;
var disk_width = 220;
function put_disks(disks) {
for (i = 0; i < disks; i++) {
// var r = Math.floor((Math.random() * 256));
// var g = Math.floor((Math.random() * 256));
// var b = Math.floor((Math.random() * 256));
str1 = "disk";
width_disks_start = width_disks_start + 10;
height_disks_start = height_disks_start - 20;
disk_width = disk_width - 30;
// eval("disks_in_twrs.push(str1 + i)" );
// disks_in_twrs[i]=c.getContext("2d");
// disks_in_twrs[i].rect((Math.random)*100,(Math.random)*100,150,100);
// disks_in_twrs[i].stroke();
// alert(disks_in_twrs);
twr1_holder.push(str1 + i);
// ctx.fillStyle = 'rgb(' + r + ',' + g + ', ' + b + ')';
// alert(str1 + i);
//twr1_holder[i] = c.getContext("2d");
eval("var disk"+i+"= c.getContext('2d');");
// twr1_holder[i].rect(width_disks_start, height_disks_start, disk_width, 20);
eval("disk"+i+".rect(width_disks_start, height_disks_start, disk_width, 20);");
// twr1_holder[i].strokeStyle = "black";
eval("disk"+i+".strokeStyle = 'black';");
// twr1_holder[i].stroke();
eval("disk"+i+".stroke();");
// alert(disk1.toSource());
}
}
function hide_me(){
alert("byeeeeeeeeeeeeeeeee");
twr1.fillRect(430, 500, 250, 250);
// disk2.rect(515, 51, 6, 20);
// disk2.strokeStyle = 'red';
}
<!DOCTYPE html>
<html>
<head>
<title>tower of Hanoi</title>
<style type="text/css">
canvas{
border : 1px solid black;
}
</style>
</head>
<body>
<label>how many disk do you want ?</label>
<input type="text" id="disk_input">
<button id="start" onclick="btn_start()">start</button>
<label>note that maximum disk is 8 :P</label>
<button id="make_hidden" onclick="hide_me()" >make me hide</button>
<canvas id="myCanvas" >
</canvas>
<script src="tower.js">
</script>
</body>
</html>
There's a lot going on here! I recommend attacking each issue in your code separately and building up understanding gradually, because this is an application that requires a lot of different components (DOM manipulation/event handlers, JS canvas, objects/arrays/loops, design, etc). If you're uncomfortable with any of these concepts, pick one area (such as DOM manipulation) and spend time working on simple, understandable examples, then apply what you learned to the main application.
Firstly, almost always avoid eval entirely. Mozilla says never to use it! If you're using it, it probably means your design has gone haywire somewhere along the line, which I would contend is the case here.
As for event handlers and document manipulation, I recommend avoiding onclick. Adding event listeners in your script can take care of the job; you'll likely be listening for clicks on the canvas to enable interaction later on.
Next: using canvas. You generally only need to retrieve the context once per application, not before each drawing. Your drawing code looks good other than this, except that it's not very DRY, which is usually a signal to redesign.
The hardest part is designing your code to meet your goals, which I'm not entirely clear on. Are you making an interactive Towers of Hanoi app, or one that simply animates a solver algorithm and requires no user input? Either way, I opted to use object constructors to represent Towers and Disks. Using arrays to hold these objects means you identify towers and disks by their position in an array rather than evaling a string name. Whenever you want to perform an action on your towers, such as drawing them, all you need to do is loop through the towers and call draw on each one. Later, when it comes to handling user input or writing a solver algorithm, it should be fairly easy to manipulate these arrays to suit your needs (e.g., figuring out which disk was clicked on, moving disks between towers, etc).
Keep in mind the below example is just a quick sketch to get you going and may not follow best design principles or ones that meet your needs. For example, I've hard-coded most drawing coordinate values, so it's non-responsive, so many exercises are left for the reader to improve on.
const Disk = function(width, color) {
this.width = width;
this.color = color;
};
const Tower = function(x, disks) {
this.x = x;
this.disks = [];
this.width = 20;
};
Tower.prototype.draw = function(c, ctx) {
ctx.lineWidth = this.width;
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.moveTo(this.x, 0);
ctx.lineTo(this.x, c.height);
ctx.stroke();
this.disks.forEach((e, i) => {
ctx.fillStyle = e.color;
ctx.fillRect(
this.x - e.width / 2,
c.height - (i + 1) * this.width,
e.width, this.width
);
});
};
const draw = (c, ctx, towers) => {
ctx.clearRect(0, 0, c.width, c.height);
towers.forEach(t => t.draw(c, ctx));
};
const initialize = disks => {
const towers = [
new Tower(c.width / 5),
new Tower(c.width / 2),
new Tower(c.width - c.width / 5)
];
for (let i = disks; i > 0; i--) {
towers[0].disks.push(
new Disk(i * 30, `hsl(${Math.random() * 360}, 50%, 50%`)
);
}
return towers;
};
document.getElementById("initialize-form")
.addEventListener("submit", e => {
e.preventDefault();
towers = initialize(parseInt(e.target.elements[0].value), towers);
draw(c, ctx, towers);
});
document.getElementById("btn-hide").addEventListener("click",
e => document.getElementById("menu").style.display = "none"
);
const c = document.getElementById("hanoi");
c.width = 600;
c.height = 200;
const ctx = c.getContext("2d");
let towers;
body {
margin: 0;
}
#hanoi {
padding: 0.5em;
}
#initialize-form {
display: inline-block;
}
#menu {
padding: 0.5em;
display: inline-block;
}
<div id="menu">
<form id="initialize-form">
<label>Enter disks:</label>
<input type="number" min="1" max="8" value="6">
<button type="submit">start</button>
</form>
<button id="btn-hide">hide</button>
</div>
<canvas id="hanoi"></canvas>
For what you are trying to do you should consider using a canvas library, maybe Konva:
https://konvajs.github.io/
Here is an example:
<script src="https://cdn.rawgit.com/konvajs/konva/2.1.7/konva.min.js"></script>
<div id="container"></div>
<script>
function KonvaRect(x, y, fill, draggable) {
return new Konva.Rect({
x: x, y: y, width: 50, height: 50,
fill: fill, stroke: 'black',
strokeWidth: 4, draggable: draggable
});
}
var boxes = [];
boxes.push(KonvaRect(50, 10, '#00D2FF', true));
boxes.push(KonvaRect(200, 10, '#0000FF', true));
boxes.push(KonvaRect(125, 10, '#FF0000', false));
var layer = new Konva.Layer();
boxes.forEach(function(b) { layer.add(b) });
var stage = new Konva.Stage({
container: 'container', width: 600, height: 170
});
stage.add(layer);
function moveCenter() {
boxes.forEach(function(b) { b.move({ x:0, y: Math.random() * 10 }) });
layer.batchDraw();
}
boxes[0].on('mouseover', function() {
moveCenter();
});
</script>
On this example I put 3 boxes in an array and when we detect the mouse over the light blue box all boxes move randomly down, also both blue boxes you can click and drag around the canvas.
And for the record there are many many other libraries out there...

Can I re-draw a canvas image with its own image?

I'm learning to draw an image with canvas and getting a problem inside this example:
let img = new Image();
img.src = 'https://image.freepik.com/free-photo/hrc-siberian-tiger-2-jpg_21253111.jpg';
let a = function () {
let c1 = document.getElementById('c1'),
c2 = document.getElementById('c2');
c1.width = c2.width = 150;
c1.height = c2.width = 150;
c1.getContext('2d').drawImage(img, 0, 0, 150, 150);
c2.getContext('2d').drawImage(img, 0, 0, 150, 150);
};
let b = function () {
let c2 = document.getElementById('c2');
c2.width = 100;
c2.height = 100;
c2.getContext('2d').drawImage(c2, 0, 0, 100, 100);
};
let c = function () {
let c1 = document.getElementById('c1'),
c3 = document.getElementById('c3');
c3.width = 100;
c3.height = 100;
c3.getContext('2d').drawImage(c1, 0, 0, 100, 100);
};
a();
b();
c();
<div>
<canvas id="c1"></canvas>
</div>
<div>
<canvas id="c2"></canvas>
</div>
<div>
<canvas id="c3"></canvas>
</div>
Inside b function. I want to re-draw (resize) its own image with another size (changing width and height from 150 to 100). But it looks like it couldn't.
Then, I've tried to make another function (c). In this function, I've used the image of canvas c1 to re-draw image of canvas c3. That's ok.
So, my question is: Cannot canvas use its own image to draw an image for itself? (or maybe I've done something wrong)
Edit: At first I thought that using an HTMLCanvasElement in the drawImage() call was an incorrect argument type. That was wrong, it's a valid argument. The actual issue was that the code was not waiting for the image to load.
You need to take a look at how you are getting your initial image data for your first canvas. I would not expect it to work because you could be drawing the image data from img before it is actually loaded. You need to attach callbacks to img to wait for it to finish loading the image and then draw that image on a canvas.
Consider my example below that includes an asynchronous way to load an image, how to draw one canvas in another, and how to draw text (just to show differences between canvases).
function loadImage(path) {
return new Promise((resolve, reject) => {
let img = new Image();
img.addEventListener("load", () => {
resolve(img);
});
img.addEventListener("error", (err) => {
reject(err);
});
img.src = path;
});
}
loadImage("https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg")
.then((img) => {
let c1 = document.getElementById("c1"),
c2 = document.getElementById("c2"),
c1Ctx = c1.getContext("2d"),
c2Ctx = c2.getContext("2d");
c1Ctx.drawImage(img, 0, 0, 150, 150);
c1Ctx.strokeText("I'm drawing on canvas 1", 25, 25);
c2Ctx.drawImage(c1, 25, 25, 100, 100);
c2Ctx.strokeText("I'm drawing on canvas 2", 25, 25);
})
.catch(console.error);
<canvas id="c1" width="150" height="150"></canvas>
<canvas id="c2" width="150" height="150"></canvas>
Another thing that you will likely run into since you want to be able to pull data out of your canvas is CORS issues. I point this out explicitly because the image that you are trying to draw onto your canvas is from a different domain (image.freepik.com in your example). Whenever you draw image data from another domain onto a canvas, that canvas becomes tainted an you can no longer use canvas' toBlob(), toDataURL(), or getImageData() methods. See: MDN: CORS enabled image.

Javascript: Moving an image created programmatically not working

I am learning javascript and I came to a point where I created an image like this:
function placeThePawn(){
base_image = new Image();
base_image.src = 'pawns/pawn_red.png';
base_image.onload = function(){
ctx.drawImage(base_image, 50, 50 , 32 , 32);
}
}
[I searched and read few tutorial to learn how to move the pawn]
Now I made a function to move the pawn (image) like this:
function moveThePawn() {
base_image.style.left = parseInt(base_image.style.left) + 100 + 'px';
}
Somehow it doesn't seem to work.
I want to know how can I implement this (move the pawn) and would also want to know why this is not working!
You will have to call the function movethePawn();
Have this in your <body onkeyup="moveSelection(event)">
and this in your script
function moveSelection(event) {
if(event.keyCode === 37) {
movethePawn();
}
}
EDIT 1 :
You may need to construct this image as an element in your DOM and have that element with document.getElementbyId and move it left. It won't work directly with an Image object
This code creates your pawn, and moves it after two seconds using only your functions (and a clearRect to remove the old icon)
var base_image;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function placeThePawn(){
base_image = new Image();
base_image.src = 'http://placehold.it/200x200';
base_image.onload = function(){
ctx.drawImage(base_image, 50, 50 , 32 , 32);
}
}
function moveThePawn() {
ctx.clearRect(0,0,200,100);
ctx.drawImage(base_image, 150, 50 , 32 , 32);
}
placeThePawn();
setTimeout(moveThePawn, 2000);
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
</canvas>
This is a better example of how to do this:
var base_image;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var clearMyCanvas = function(){ctx.clearRect(0,0,1000,1000)};
var pawn = {
x:50,
y:50,
h:32,
w:32,
render: function placeThePawn(){
base_image = new Image();
base_image.src = 'http://placehold.it/200x200';
base_image.onload = function(){
ctx.drawImage(base_image, pawn.x, pawn.y , pawn.w , pawn.h);
}
}
}
pawn.render();
// redraw all the things you want on your next screen here.
setTimeout(function(){
// clear canvas
clearMyCanvas();
// perform logics
pawn.x += 100;
// redraw
pawn.render()
}, 2000);
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
</canvas>
I think you are mixing up the html5 canvas element (as seen in ctx.drawImage(base_image, 50, 50 , 32 , 32);) with simple html and css.
this line: base_image.style.left = parseInt(base_image.style.left) + 100 + 'px'; is attempting to change the css style property of an element saved in a variable called base_image. But there is no such element.
What you need to change is not the style of base_image, but the canvas context ctx where base_image has been drawn.
function moveThePawn() {
ctx.drawImage(base_image, 50, 50 , 32 , (32+100));//add the 100 pixels to the canvas rendering of the image
}

increase performance on html canvas mousemove image mask

I have a canvas that is drawing an image and clipping to create the effect that the image is being revealed. I have the code working properly I have tried using a debouce method and also rAF to increase the canvas rendering performance but I only saw small gains if any.
I suspect the way I am iterating through my array of x and y coordinates could be the issue.
It seems to lag quite a bit when it is out putting the array in console about the same rate as the circle appear on the screen.
Here is the redraw function:
function redraw(mouse) {
m.push(mouse);
m.forEach(function (a) {
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.rect(0, 0, 500, 500);
ctx.arc(a.x, a.y, 70, 0, Math.PI * 2, true);
ctx.clip();
ctx.fillRect(0, 0, 500, 500)
})
}
I guess what I am looking for is some advice to speed up my code so the rendering of the circles seems more like drawing.
Here is the working demo -> http://jsfiddle.net/naeluh/4h7GR/
There are several issues here :
• Your mouse code is a nightmare, traversing the DOM on every move.
• You are redrawing everything on each move.
So i suggest a way more efficient solution :
• stack two canvases, the one below is your image, the one on top is the mask.
• Deal efficiently with the mouse.
• Only clear part of the mask canvas on mouse move : just one circle drawn on the mask canvas for each move.
(for that i used a globalCompositeOperation = 'destination-out' )
Result is perfectly smooth either on Firefox, Chrome, or Safari .
(tested on mac OS).
the fiddle :
(you have to click to clear)
http://jsfiddle.net/gamealchemist/4h7GR/22/
html
<canvas style='position: absolute; top: 0;left: 0;' id="canvas1" width="500" height="500"></canvas>
<canvas style='position: absolute;top: 0;left: 0;' id="canvas2" width="500" height="500"></canvas>
js
var can = document.getElementById("canvas1");
var ctx = can.getContext("2d");
var can2 = document.getElementById("canvas2");
var ctx2 = can2.getContext("2d");
var img = new Image();
img.onload = function () { ctx.drawImage(img,0,0); };
img.src = "http://placekitten.com/500/500";
ctx2.fillStyle='#000';
ctx2.fillRect(0,0,500,500);
ctx2.globalCompositeOperation = 'destination-out';
function clearThis(x,y) {
console.log('toto');
ctx2.fillStyle='#F00000';
ctx2.beginPath();
ctx2.arc(x, y, 70, 0, Math.PI * 2, true);
ctx2.fill();
}
var mouse = {
x: 0,
y: 0,
down: false
};
function setupMouse(canvas, onMouseMove, preventDefault) {
var rectLeft, rectTop;
var hook = canvas.addEventListener.bind(canvas);
var mouseDown = updateMouseStatus.bind(null, true);
var mouseUp = updateMouseStatus.bind(null, false);
hook('mousedown', mouseDown);
hook('mouseup', mouseUp);
hook('mousemove', updateCoordinates);
hook('scroll', updateRect);
// var mouseOut = function() { mouse.down=false ; } ;
// hook('mouseout', mouseOut);
function updateMouseStatus(b, e) {
mouse.down = b;
updateCoordinates(e);
if (preventDefault) {
e.stopPropagation();
e.preventDefault();
}
}
function updateCoordinates(e) {
mouse.x = (e.clientX - rectLeft);
mouse.y = (e.clientY - rectTop);
onMouseMove(mouse.x, mouse.y);
}
function updateRect() {
var rect = canvas.getBoundingClientRect();
rectLeft = rect.left;
rectTop = rect.top;
}
updateRect();
};
setupMouse(can2, clearThis, true);
The Above Code will do Fine .. But nEed some Editing
I have Edited the Code in Fiddle ..and i beleive there Is some Improvement in perforamnce
So I looked a little more and found a bug as expected.
The main problem is the accumulation of the drawing path.
Why Need to add clip and fillRect at every go ..Do it at last... the Major issue solved,Like
can.addEventListener("mousemove", function (e) {
var mouse = getMouse(e, can);
requestAnimationFrame(function () {
redraw(mouse);
ctx.clip();
ctx.fillRect(0, 0, 500, 500);
console.log(mouse);
});
}, false);
2.The Updated JSFiidle is
UpdatedFiddle

HTML5 draw text that stays on the top

I am creating a file called functions.js with diferent functions like:
bgImage()
drawImage()
setText()
My issue is that my text keeps staying behind.
What i want to do is, when i call setText() i can put text where i want. And the text will be put on the top ofc the convas. I know i need to call the image draw load functions first to get them to not overwrite my text. But i did so in my JS.
So its very important that i can call the function setText() as many times as i want, after all images are drawn/set, and the text will be visible.
I want the text on the top.
Here is my code:
functions.js
var canvas = "";
var context = "";
function canvasInit() {
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');
}
function bgImage() {
var imageObj = new Image();
imageObj.onload = function() {
var pattern = context.createPattern(imageObj, 'repeat');
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = pattern;
context.fill();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/wood-pattern.png';
}
function drawImage() {
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 10, 50);
context.drawImage(imageObj, x, y, width, height);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
}
function (text) {
context.font = 'italic 40pt Calibri';
context.fillText(text, 150, 100);
}
index.html
<!DOCTYPE html>
<html>
<head>
<script src="functions.js"></script>
<script>
document.addEventListener('DOMContentLoaded',ready);
function ready() {
canvasInit();
bgImage();
drawImage();
setText("Yo");
setText("heyyyy");
}
</script>
</head>
<body>
<canvas id="myCanvas" width="500" height="400"></canvas>
</body>
</html>
Updated test that do not work:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="functions.js"></script>
<script>
document.addEventListener('DOMContentLoaded',ready);
function ready() {
canvasInit();
bgImage(function() {
setText();
});
}
</script>
</head>
<body>
<canvas id="myCanvas" width="500" height="400"></canvas>
</body>
</html>
functions.js
var canvas = "";
var context = "";
function canvasInit() {
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');
}
function bgImage(callback) { // add parameter for function
var imageObj = new Image();
imageObj.onload = function() {
var pattern = context.createPattern(imageObj, 'repeat');
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = pattern;
context.fill();
if (typeof callback === 'function') {
callback(); // invoke callback function
}
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/wood-pattern.png';
}
function drawImage() {
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 10, 50);
context.drawImage(imageObj, x, y, width, height);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
}
function setText() {
context.font = 'italic 40pt Calibri';
context.fillText("Yoo adfa ds asd a sd", 150, 100);
}
It happens because your image loading is asynchronous: before the image has finished loading you draw your text as the function exits after setting the source. Then when the image has finished loaded the onload function is called and the image drawn on top of whatever is drawn previously (in this case the text).
You need to implement a callback handler for your functions for this to work - for example:
function bgImage(callback) { /// add parameter for function
var imageObj = new Image();
imageObj.onload = function() {
var pattern = context.createPattern(imageObj, 'repeat');
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = pattern;
context.fill();
if (typeof callback === 'function')
callback(); /// invoke callback function
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/wood-pattern.png';
}
Then you use it:
bgImage(function() {
setText();
});
You will of course need to do this with the other image loading functions as well. Tip: If you end up with a long chain it's probably better to assign non-anonymous functions instead of inline them as in the last example.
Update:
Just for clarity: it's important that the function provided is provided as a reference and not a result from calling, for example: use the callback this way:
bgImage(setText); /// correct
not this way:
bgImage(setText()); /// wrong
With the parenthesis the setText is simply invoked and its result is passed as a callback. This means the text will be drawn first and then bgImage is called.
I never got my code to work. However i found some framework called "http://kineticjs.com/" and i solved my issues using that.
Thanks for the comments Ken - Abdias Software. I did also take a look at what you linked to in your profile description. Looking really neat ;)
However i feel its the best to accept the answer that solved my problem, and i solved it myself.
Thanks again :)

Categories