Resizing Canvas Elements with Mouse Events with EaselJS - javascript

I'm trying to draw elements to a canvas and then allow the user to resize them by clicking and dragging them. I've implemented this with Kinetic JS library, but my development team is moving over to Easel JS.
Here is the code with the Kinetic library.
This works well enough.
I get about this far in Easel JS, but this code doesn't do anything. The canvas is totally blank. I realize that I'm not sure how to:
call mouse events -- here I'm trying to attach them to the DOM element, as in this tutorial
where to set the resize function -- separate function? called within the tick() function?
grab the mouse coordinates
var canvas;
var stage;
var rect;
var mousePos = new Point();
var update = true;
var rectX = 10;
var rectY = 10;
var rectW = 100;
var rectH = 50;
var rectXOffset = 50;
var rectYOffset = 50;
var newWidth;
var newHeight;
function init() {
// create stage and point it to the canvas:
canvas = document.getElementById("testCanvas");
stage = new Stage(canvas);
// overlay canvas used to draw target and line
canvasWrapper = $("#testCanvas");
// listen for a mouse down event
canvasWrapper.mousedown(onMouseDown);
// listen for mouse up event
canvasWrapper.mouseup(onMouseUp);
// enable touch interactions if supported on the current device:
if (Touch.isSupported()) { Touch.enable(stage); }
// enabled mouse over / out events
stage.enableMouseOver(10);
// start drawing instructions
var rect = new Shape();
rect.graphics
.setStrokeStyle(1)
.beginStroke(Graphics.getRGB(25,25,112,.7))
.drawRect(rectX,rectY,rectW,rectH);
// add rectangle to stage
stage.addChild(rect);
// render stage
stage.update();
// set the tick interval to 24 fps
Tick.setInterval(1000/24);
// listen for tick event
Tick.addListener(window, true);
// pause
Tick.setPaused(false);
}
//called when user clicks on canvas
function onMouseDown(e) {
mousePos.x = e.stageX;
mousePos.y = e.stageY
// check to see if mouse is within offset of rectangle
if(mousePos.x <= (rectW + rectXOffset) || mousePos.y <= (rectH + rectYOffset)) {
// set update to true
update = true;
// unpause tick
Tick.setPaused(false);
}
}
function onMouseUp(e) {
update = false;
Tick.setPaused(true);
}
function tick() {
// this set makes it so the stage only re-renders when an event handler indicates a change has happened.
if (update) {
if(mousePos.x - rectX < 50)
{
newWidth = 50;
} else {
newWidth = mousePos.x - rectX;
}
if(mousePos.y - rectY < 50)
{
newHeight = 50;
} else {
newHeight = mousePos.y -rectY;
}
rectW = newWidth;
rectH = newHeight;
rect.clear();
rect.graphics
.setStrokeStyle(1)
.beginStroke(Graphics.getRGB(65,65,65,.7))
.drawRect(0,0,rectW,rectH);
// add rectangle to stage
stage.addChild(rect);
update = false; // only update once
stage.update();
}
}
I know it shouldn't be this difficult and would appreciate any help.

Related

Uncaught TypeError: Cannot set property 'onclick' of null. Tried window.onload

So, I'm relatively new to Javascrip. Though what I want to do is give a moving image on my canvas an id, so that I can ultimately use onclick to use the image as a clickable image, so I can redirect the user to another page, which is what would happen when the image is clicked. Here is my code so far. I need help. If you need any more clarification I will try to explain further.
var ctx;
var imgBg;
var imgDrops;
var x = 0;
var y = 0;
var noOfDrops = 50;
var fallingDrops = [];
function drawBackground(){
ctx.drawImage(imgBg, 0, 0); //Background
}
function draw() {
drawBackground();
for (var i=0; i< noOfDrops; i++)
{
ctx.drawImage (fallingDrops[i].image, fallingDrops[i].x, fallingDrops[i].y); //The rain drop
fallingDrops[i].y += fallingDrops[i].speed; //Set the falling speed
if (fallingDrops[i].y > 1000) { //Repeat the raindrop when it falls out of view
fallingDrops[i].y = -25 //Account for the image size
fallingDrops[i].x = Math.random() * 10000; //Make it appear randomly along the width
}
}
}
function setup() {
var canvas = document.getElementById('canvasRegn');
if (canvas.getContext) {
ctx = canvas.getContext('2d');
imgBg = new Image();
imgBg.src = "http://images.susu.org/unionfilms/films/backgrounds/hd/space-jam.jpg";
setInterval(draw, 36);
for (var i = 0; i < noOfDrops; i++) {
// Charles Barkley
var fallingDr = new Object();
fallingDr["image"] = new Image();
fallingDr.image.src = 'http://xenboards.ignimgs.com/external_data/attachments/8/8795-f09b907a01726a25ca2fbd2f588e3f0e.jpg';
fallingDr["x"] = Math.random() * 10000;
fallingDr["y"] = Math.random() * 5;
fallingDr["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr);
// Bugs bunny
var fallingDr2 = new Object();
fallingDr2["image"] = new Image();
fallingDr2.image.src = 'http://i.imgur.com/zN2CSAf.png'
fallingDr2["x"] = Math.random() * 10000;
fallingDr2["y"] = Math.random() * 5;
fallingDr2["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr2);
// Michael Jordan
var fallingDr3 = new Object();
fallingDr3["image"] = new Image();
fallingDr3.image.src = 'http://i.imgur.com/XxvJiGg.png'
fallingDr3["x"] = Math.random() * 10000;
fallingDr3["y"] = Math.random() * 5;
fallingDr3["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr3);
// Daffy duck
var fallingDr4 = new Object();
fallingDr4["image"] = new Image();
fallingDr4.image.src = 'http://i.imgur.com/QZogw2L.png'
fallingDr4["x"] = Math.random() * 10000;
fallingDr4["y"] = Math.random() * 5;
fallingDr4["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr4);
fallingDr4.image.id = "Daffy";
}
}
}
setup();
window.onload = function(){
document.getElementById("Daffy").onclick=function(){
alert("Hello World");
}
}
Try:
fallingDr4.image.onclick=function(){
alert(this.id);
}
should alert "Duffy".
Your problem is that you're trying to catch the click event on an element that is not in the document and hence, not clickable by the user.
When you call var img = new Image() a new <img> element is created, with all its properties that you can already modify in your javascript. But this element is only available to your scripts, and is not displayed into the page until you call document.anyElement.appendChild(img). So it's better to consider this as an imageObject more than to an element (even if it actually also is).
What is in your document, and accessible to your user, is the <canvas> element. So if you want to know if the user has clicked, you will have to attach the eventListener to this canvasElement.
But the canvasElement doesn't know what it does represent. When you call context.drawImage(), you're just applying the pixels from the imageSource to the ones of the canvas, and all reference to the original imageObject are lost.
To workaround this, you'll then have to store the position of your drawn image into the canvas, and then check if the click event you caught was inside these positions.
Click events' clientX and clientY properties of the Event passed as arguments of you handler will give you the position of the cursor when the event occurred. But the positions are relative to the top-left corner of the window. So you'll also need to make these relative to the top-left corner of your canvas, which can be done by calling the getBoundingClientRect() method of the canvasElement.
Here is a simplified example :
// this function will be called at image's load
var init = function() {
// a reference to our "in-screen" canvasElement
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// "kitty" will be the js object that will help us know if we clicked on our image
// "this" refers to the imageObject
var kitty = {
width: this.width,
height: this.height,
// random positions
left: Math.random() * (canvas.width - this.width),
top: Math.random() * (canvas.height - this.height),
};
// draw our image at the random positions we created
ctx.drawImage(this, kitty.left, kitty.top, kitty.width, kitty.height);
// here we're listening to mousemove event,
// but click event shares the same clientX & clientY properties
var moveHandler = function(evt) {
// in the "evt" object passed, we can get the x and y positions relative to the window
// so we make these relatives to the canvas ones
var canvasRect = canvas.getBoundingClientRect();
var x = evt.clientX - canvasRect.left;
var y = evt.clientY - canvasRect.top;
// now we've got our relative positions, we can check if we were inside the image
if (x >= kitty.left && x <= (kitty.left + kitty.width) && y >= kitty.top && y <= (kitty.top + kitty.height) ) {
// we are over the image, do something
canvas.style.cursor = 'pointer';
document.body.style.backgroundColor = 'lightblue';
} else {
canvas.style.cursor = 'default';
document.body.style.backgroundColor = 'transparent';
}
};
// attach this event handler to the canvasElement
canvas.addEventListener('mousemove', moveHandler);
};
// this will create an imageObject, which will stay "off-screen" (never appendded to the document)
var img = new Image();
// wait that the image has loaded before trying to make any magic
img.onload = init;
img.src = "http://lorempixel.com/200/70/cats";
body {
width: 100vw;
text-align: center;
}
canvas {
margin: 0 auto;
position: relative;
}
<canvas id="canvas" width="500" height="500"></canvas>
(you may need to scroll to actually see the image, or go fullscreen)

How to move image on canvas using arrow keys in javascript

I've tried a few different ways that I have seen on here, but I can't quite get my image to move. Whenever I try adapting code for arrow key presses, it just seems to make my canvas shrink and my player model (spaceperson) disappear.
here is the "drawing board" I keep returning to, and what I have so far.
// Get the canvas and context
var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 700;
// Create the image object
var spaceperson = new Image();
// Add onload event handler
spaceperson.onload = function () {
// Done loading, now we can use the image
ctx.drawImage(spaceperson, 280, 300);
};
// artwork by Harrison Marley (using make8bitart.com)
spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";`
I am quite new to javascript, and I am just trying to work out how I can move the specperson image using arrow keys. I was trying to make a class for space person to access their x,y values, but I can't seem to draw the image without using .onload
here a more complete example:
//just a utility
function image(url, callback){
var img = new Image();
if(typeof callback === "function"){
img.onload = function(){
//just to ensure that the callback is executed async
setTimeout(function(){ callback(img, url) }, 0)
}
}
img.src = url;
return img;
}
//a utility to keep a value constrained between a min and a max
function clamp(v, min, max){
return v > min? v < max? v: max: min;
}
//returns a function that can be called with a keyCode or one of the known aliases
//and returns true||false wether the button is down
var isKeyDown = (function(aliases){
for(var i=256, keyDown=Array(i); i--; )keyDown[i]=false;
var handler = function(e){
keyDown[e.keyCode] = e.type === "keydown";
e.preventDefault(); //scrolling; if you have to suppress it
};
addEventListener("keydown", handler, false);
addEventListener("keyup", handler, false);
return function(key){
return(true === keyDown[ key in aliases? aliases[ key ]: key ])
}
})({
//some aliases, to be extended
up: 38,
down: 40,
left: 37,
right: 39
});
// Get the canvas and context
var canvas = document.getElementById("space");
canvas.width = 1920;
canvas.height = 700;
var ctx = canvas.getContext("2d");
//the acutal image is just a little-part of what defines your figue
var spaceperson = {
image: image("//i.imgur.com/Eh9Dpq2.png", function(img){
spaceperson.width = img.naturalWidth;
spaceperson.height = img.naturalHeight;
//start the rendering by calling update
update();
}),
//position
x: 60, y: 310,
width: 0, height: 0,
speed: 200 // 200px/s
};
var lastCall = 0; //to calculate the (real) time between two update-calls
//the render-fucntion
function update(){
//taking account for (sometimes changing) framerates
var now = Date.now(), time = lastCall|0 && (now-lastCall)/1000;
lastCall = now;
requestAnimationFrame(update);
var sp = spaceperson,
speed = sp.speed;
//checking the pressed buttons and calculates the direction
//two opposite buttons cancel out each other, like left and right
var dx = (isKeyDown('right') - isKeyDown('left')) * time,
dy = (isKeyDown('down') - isKeyDown('up')) * time;
//fix the speed for diagonals
if(dx && dy) speed *= 0.7071067811865475; // * 1 / Math.sqrt(2)
if(dx) { //there is some movement on the x-axes
sp.x = clamp(
//calculate the new x-Position
//currentPos + direction * speed
sp.x + dx * sp.speed,
//restraining the result to the bounds of the map
0, canvas.width - sp.width
);
}
//same for y
if(dy) sp.y = clamp(sp.y + dy * sp.speed, 0, canvas.height - sp.height);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(sp.image, sp.x, sp.y);
}
Edit:
A quick question (I hope); if I was to later add other objects, would I check for collisions in update()?
This is still just a very basic example. The main purpose of the update()-function should be to work as the main event-loop.
To trigger all Events that have to happen each frame in the order they have to happen.
var lastCall = 0;
function update(){
//I always want a next frame
requestAnimationFrame(update);
//handle timing
var now = Date.now(),
//time since the last call in seconds
//cause usually it's easier for us to think in
//tems like 50px/s than 0.05px/ms or 0.8333px/frame
time = lastCall|0 && (now-lastCall) / 1000;
lastCall = now;
movePlayer(time);
moveEnemies(time);
moveBullets(time);
collisionDetection();
render();
}
function render(){
ctx.clear(0, 0, canvas.width, canvas.height);
drawBackground(ctx);
for(var i=0; i<enemies.length; ++i)
enemies[i].render(ctx);
player.render(ctx);
}
Not saying that you have to implement all these functions now, but to give you an idea of a possible structure.
Don't be scared to break big tasks (functions) up into subtasks.
And it might make sense to give each enemy a move()-function so you can implement different movement-patterns per enemy,
or you say that the pattern is (and will be) all the same for each enemy, parameterized at the best, then you can handle that in a loop.
Same thing for rendering, as I'm showing in the last part of code.
Here's some slightly modified code from a game I was noodling around with a while back. If you want to see more code, check out the complete JS on GitHub. The game is incomplete but you should gather some helpful clues as to how to move an image around the canvas.
var spaceperson = {
speed: 256,
other_stuff: ''
},
keysDown = [],
update,
main;
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
update = function (modifier) {
if (38 in keysDown && spaceperson.y > 0) { // UP
spaceperson.y -= spaceperson.speed * modifier;
}
if (40 in keysDown && spaceperson.y < CANVAS_HEIGHT - SPACEPERSON_HEIGHT) { // DOWN
spaceperson.y += spaceperson.speed * modifier;
}
if (37 in keysDown && spaceperson.x > 0) { // LEFT
spaceperson.x -= spaceperson.speed * modifier;
}
if (39 in keysDown && spaceperson.x < CANVAS_WIDTH - SPACEPERSON_WIDTH) { // RIGHT
spaceperson.x += spaceperson.speed * modifier;
}
}
I'm not sure but i think this can help.
// Get the canvas and context
var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 700;
var x = 280;
var y = 300;
// Create the image object
var spaceperson = new Image();
spaceperson.addEventListener("keypress", press);
// Add onload event handler
spaceperson.onload = function () {
// Done loading, now we can use the image
ctx.drawImage(spaceperson, x, y);
};
function press(event) {
if(event.keyCode == 37) {//LEFT
x = x - 1;
} else if(event.keyCode == 38) {//UP
y = y - 1;
} else if(event.keyCode ==39) {//RIGHT
x = x + 1;
} else if(event.keyCode == 40) {//DOWN
y = y + 1;
}
draw();
}
function draw(){
ctx.drawImage(spaceperson,x,y);
}
// artwork by Harrison Marley (using make8bitart.com)
spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";
I found a solution!
// Get the canvas and context
var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 700;
var xPos = 60;
var yPos = 310;
// Create the image object
var spaceperson = new Image();
// Add onload event handler
spaceperson.onload = function () {
// Done loading, now we can use the image
ctx.drawImage(spaceperson, xPos, yPos);
};
function move(e){
if(e.keyCode==39){
xPos+=10;
}
if(e.keyCode==37){
xPos-=10;
}
if(e.keyCode==38){
yPos-=10;
}
if(e.keyCode==40){
yPos+=10;
}
canvas.width=canvas.width;
ctx.drawImage(spaceperson, xPos, yPos);
}
document.onkeydown = move;
// artwork by Harrison Marley
spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";

html5 draw gaussian function using bezierCurveTo

I have been trying to draw gaussin-like function using bezierCurveTo
find the code below
<canvas id="thisCan" width="0px" height="0px" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
(function() {
var
// Obtain a reference to the canvas element
// using its id.
htmlCanvas = document.getElementById('thisCan'),
// Obtain a graphics context on the
// canvas element for drawing.
ctx = htmlCanvas.getContext('2d');
var width = 0;
var height = 0;
// Start listening to resize events and
// draw canvas.
initialize();
function initialize()
{
// Register an event listener to
// call the resizeCanvas() function each time
// the window is resized.
window.addEventListener('resize', resizeCanvas, false);
// Draw canvas border for the first time.
resizeCanvas();
}
// Display custom canvas.
// In this case it's a blue, 5 pixel border that
// resizes along with the browser window.
function redraw()
{
ctx.beginPath();
ctx.moveTo(width/2, 0);
ctx.bezierCurveTo(150, 119, 186, 121, 66, 185);
ctx.moveTo(width/2 + width * 0.08 , 0);
ctx.bezierCurveTo(344, 119, 344, 121, 504, 185);
ctx.stroke();
}
// Runs each time the DOM window resize event fires.
// Resets the canvas dimensions to match window,
// then draws the new borders accordingly.
function resizeCanvas()
{
var contentElement = document.getElementsByClassName("content-box post")[0]
width = htmlCanvas.width = (contentElement.clientWidth * 0.75)
height = htmlCanvas.height = (contentElement.offsetWidth*0.75 * 0.5);
redraw();
}
})();
</script>
I am planning to draw many curves in between as well. But how do I make it parametric, based on width and height variables?
I need to specify the control points using width and height parameters, so that it becomes window-size invariant.
Is there a way?
Don't use Bezier curves if you want an exponent curve, they're different functions. Instead, just plot the function you actually need, with something like http://jsbin.com/nubutodosu/edit?js,output, where you define a Gaussian object:
// Gaussian distribution generator
var Gaussian = function(mean, std) {
this.mean = mean;
this.std = std;
this.a = 1/Math.sqrt(2*Math.PI);
};
Gaussian.prototype = {
addStd: function(v) {
this.std += v;
},
get: function(x) {
var f = this.a / this.std;
var p = -1/2;
var c = (x-this.mean)/this.std;
c *= c;
p *= c;
return f * Math.pow(Math.E, p);
},
generateValues: function(start, end) {
var LUT = [];
var step = (Math.abs(start)+Math.abs(end)) / 100;
for(var i=start; i<end; i+=step) {
LUT.push(this.get(i));
}
return LUT;
}
};
And then you can give that a draw routine so that it can plot itself over the interval that you need:
...
draw: function(ctx) {
var points = this.generateValues(-10,10);
var len = points.length;
ctx.strokeStyle = "black";
ctx.beginPath();
var p0 = points[0];
ctx.moveTo(0, height - (height*p0));
points.forEach(function(p,i) {
if(i===0) {
return;
}
ctx.lineTo(width * i/len, height - (height*p));
p0 = p;
});
ctx.stroke();
}
...
So you build your array of values over the interval, then draw them on the canvas by "connecting the dots".
I managed to resolve it.
To be specific, I was looking out for half-gaussian curve.
I managed to figure out that guassian function has a very special property with respect to bezier curves. It might be elementary, but I could not find it on google. So this might be informative finding.
If each control points of the cubic bezier curve reside on a "line parallel to X axis and passing through start point/end point", the resulting curve will be of a half guassian shape.
e.g.
On top of this finding, I have written the following code:
<canvas id="thisCan" width="0px" height="0px">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
(function() {
var
// Obtain a reference to the canvas element
// using its id.
htmlCanvas = document.getElementById('thisCan'),
// Obtain a graphics context on the
// canvas element for drawing.
ctx = htmlCanvas.getContext('2d');
// Start listening to resize events and
// draw canvas.
initialize();
function initialize()
{
// Register an event listener to
// call the resizeCanvas() function each time
// the window is resized.
window.addEventListener('resize', resizeCanvas, false);
// Draw canvas border for the first time.
resizeCanvas();
}
// Display custom canvas.
// In this case it's a blue, 5 pixel border that
// resizes along with the browser window.
function redraw(width, height)
{
var start = width/2;
var margin = width * 0.01;
var height = (width / 3) - (margin * 4);
var end_step = width/4
ctx.beginPath();
ctx.moveTo(start - margin, 0);
ctx.bezierCurveTo((start - height/3), 0 , (start - height/3), height , end_step*1, height);
ctx.moveTo(start + margin, 0);
ctx.bezierCurveTo((start + height/3), 0 , (start + height/3), height , end_step*3, height);
ctx.moveTo(start - margin, 0);
ctx.bezierCurveTo((start - height*0.33), 0 , (start - height*0.16), height , end_step*1.5, height);
ctx.moveTo(start + margin, 0);
ctx.bezierCurveTo((start + height*0.33), 0 , (start + height*0.16), height , end_step*2.5, height);
ctx.moveTo(start, 0);
ctx.bezierCurveTo((start ), 0 , (start ), height , end_step*2, height);
ctx.stroke();
}
// Runs each time the DOM window resize event fires.
// Resets the canvas dimensions to match window,
// then draws the new borders accordingly.
function resizeCanvas()
{
var width = 0;
var height = 0;
var contentElement = document.getElementsByClassName("content-box post")[0]
width = htmlCanvas.width = (contentElement.clientWidth * 0.85)
height = htmlCanvas.height = (contentElement.offsetWidth*0.85 * 0.33);
redraw(width, height);
}
})();
</script>
and the output:

Changing canvas drawn image on mouseover

I'm really struggling with the changing of my canvas drawn image so I thought I would see if anyone could assist me on here or offer advice.
I've drawn a static flag in canvas, and I've also drawn a waving flag. I'm trying to get this flag to wave on mouseover.
I initially thought that I was going to have to create two separate files, one for the static and one for the waving aspect. Then save each of them as a jpg/gif image using window.location = canvas.toDataURL("image/");.
But I've just discovered that you can apparently do this all in the same file via jquery/hover. Which seems a lot simpler and a more efficient way of doing it.
Here is the code for the waving flag:
window.onload = function(){
var flag = document.getElementById('banglaFlag');
banglaStatic( flag, 320 );
var timer = banglaWave( flag, 30, 15, 200, 200 );
};
function banglaStatic( canvas, width ){
//Drawing the Bangladesh flag.
//Declaring variables that regard width and height of the canvas.
//Variables C to L are needed for the waving function.
var a = width / 1.9;
var b = 200;
var c = 7*a/13;
var l = a / 13;
canvas.width = b;
canvas.height = a;
var ctx = canvas.getContext('2d');
var radius = 45;
};
function banglaWave( canvas, wavelength, amplitude, period, shading ){
var fps = 30;
var ctx = canvas.getContext('2d');
var w = canvas.width, h = canvas.height;
var od = ctx.getImageData(0,0,w,h).data;
// var ct = 0, st=new Date;
return setInterval(function(){
var id = ctx.getImageData(0,0,w,h);
var d = id.data;
var now = (new Date)/period;
for (var y=0;y<h;++y){
var lastO=0,shade=0;
for (var x=0;x<w;++x){
var px = (y*w + x)*4;
var o = Math.sin(x/wavelength-now)*amplitude*x/w;
var opx = ((y+o<<0)*w + x)*4;
shade = (o-lastO)*shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData(id,0,0);
// if ((++ct)%100 == 0) console.log( 1000 * ct / (new Date - st));
},1000/fps);
}
Thanks in advance for any advice/assistance.
I am not sure where your problem is. I did not see any event handling code, so I assume that's your question:
Define a function to "handle the mouse event". For example, if you want to move the flag when the user moves the mouse over it, define something like:
function mouseMove(event) {
var mouseX,
mouseY;
event.preventDefault(); // stops browser to do what it normally does
// determine where mouse is
mouseX = event.pageX;
mouseY = event.pageY;
// do something useful, e.g. change the flag to waving when mouse is over flag
}
Then, register this function to be called when the mouse moves:
canvas.addEventListener("mousemove", mouseMove, false);
canvas is the canvas you paint the flag on, "mousemove" is the name of the event (many more exist, such as "mousedown", "mouseup", "mouseout" (leaving canvas), "mousewheel", etc.), mouseMove is the name of your function (the event handler, as it's called).
Events are a little different from browser to browser (and even browser version), so you might need to implement different event handler if you need it across browsers.
Hoping this helped...
canvas is like a sheet. there is no any object on which you can hover.
for doing what you wanted to do is just,bound an area on the flag,
follow the 'virtualnobi' answer and calculate if mouse co-ordinate falls on that region,
if true do what ever you want.
like
if (mouseX<100 && mouseX>0 && mouseY>0 && mouseY<100){
//animate the flag
}
use mouseX=event.clientX;
mouseY=event.clientY;
bounded area is x=(0,100) , y=(0,100) here.

How to assign onclick on image drawn in canvas?

I'm trying to get an event to work on an image when the user clicks on it.
var canvas = document.createElement("canvas");
canvas.width = 800;
canvas.height = 600;
canvas.style = "border:2px solid black";
canvas.addEventListener('click', clickReporter, false);
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var clickhere = new Image();
clickhere.onload = function () {
draw();
};
clickhere.src = "clickhere.png";
function draw() {
ctx.drawImage(clickhere, 200, 200);
}
function clickReporter(e) {
alert("Thanks for clicking!");
}
Obviously all this code will just let the alert box go off as long as the user clicks in the canvas. The image is 100 by 100 pixels.
First off: You apparently have an error in you code in regards to the image (at least in the example you provide):
var button = new Image();
clickhere.onload = function () {
draw();
};
clickhere.src = "clickhere.png";
function draw() {
ctx.drawImage(clickhere, 200, 200);
}
Should be like this for the example to work:
var button = new Image();
/// use button for these as well -
button.onload = function () { /// here
draw();
};
button.src = "clickhere.png"; /// here
function draw() {
ctx.drawImage(button, 200, 200); /// and here (or use 'this' instead)
}
The next problem
Canvas doesn't know what we draw into it so we need to make sure we provide all the underlying logic ourselves to handle these sort of things.
For example: Here is one way to check if the region the image was drawn into is clicked:
function clickReporter(e) { /// assign event to some variable
/// adjust mouse click position to be relative to canvas:
var rect = this.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top;
/// check x/y coordinate against the image position and dimension
if (x >= 200 && x <= (200 + button.width) &&
y >= 200 && y <= (200 + button.height)) {
alert("Thanks for clicking!");
}
}
You might want to convert those semi-absolute bounds to something more dynamic by for example using an image with a custom object where you store its x and y position and so forth. But you should get the idea.
Update:
A modified fiddle here

Categories