I'm trying to add an eventlistener to a picture so once clicked it takes me to a different page, at the moment I have it taking me to the next page but not when I click the picture, but when I click anywhere on the canvas
Responding to canvas click events
Oops, it looks like your question was cut off! On your next question, be sure not to hit the “Enter” key—instead of starting a new line in your question, you will immediately post your partially written question (don’t worry…we’ve all done it).
And Nick, “Welcome to stackoverflow” – it really is full of answers!
Norguard is right about the canvas not being able to keep track of which image you clicked on. Think of canvas as an artist's easel and you are painting images on that easel. Yes, the easel contains the images, but the easel has no way of knowing where you drew any image.
To keep your life simple while you’re learning, try starting with having just 1 image per canvas (yes, you can have as many canvas elements as you have images).
If you want to start with 1 image per canvas, here is code and a Fiddle: http://jsfiddle.net/m1erickson/KGKYg/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
}
img.src="http://dl.dropbox.com/u/139992952/coffee.png";
canvas.addEventListener("click", function (e) { alert("use your linke totake me away...!"); });
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
[Edit: Responding to keyboard events]
Here's how you can listen for user keypresses and respond to them:
// listen for keyboard events
window.addEventListener('keydown',keyIsDown,true);
// process the keystrokes
function keyIsDown(event){
switch (event.keyCode) {
case 38:
// "UP" was pressed, do UP stuff
break;
case 40:
// "DOWN" was pressed, do DOWN stuff
break;
}
}
You can't do this simply, and there's no event listener that will let you.
1) listen for the click on the canvas
2) keep a reference to the image object that you drew... ...as in, know its canvas coordinates, by keeping reference in a separate object:
var canvas_img = {
x : 250,
y : 300,
data : my_img,
width : my_img.width,
height : my_img.height
};
3) on click of the canvas, manually calculate whether a collision happened between where the click happened on the canvas, and where the image is on the canvas.
Related
I know this question has already been asked several times, however, I haven't
found a solution yet.
I want to take an image, rotate it and put it in a HTML canvas, to do this I'm using another canvas in which I rotate the image, this part works well, however, when I try to take the image from the second canvas using .toDataUrl, it returns a blank image. The code is the following
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id=canvas height="400" width="400" style="border: 10px solid orange"></canvas>
<canvas id=canvasTransform height="183" width="183" style="border: 10px solid orange"></canvas>
<script type="text/javascript">
//this is the canvas in which I want to put the rotated image
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
//and I use this one to rotate it
var canvasTransform=document.getElementById('canvasTransform');
var contextTransform=canvasTransform.getContext("2d");
var image=new Image(46,183);
image.onload=function(){
contextTransform.drawImage(image,0,0);
}
image.src="Fireball.png";
console.log(image.src);
//Now I rotate the context
contextTransform.rotate(-0.25*Math.PI);
//After doing this, I can see the rotated image in the second canvas, however, the following line returns a blank image
var rotatedImageURL=canvasTransform.toDataURL();
console.log(rotatedImageURL);
//Finally, this part isn't wornking since I just draw a blank image
var rotatedImage=new Image();
rotatedImage.onload=function(){
context.drawImage(rotatedImage,0,0);
}
rotatedImage.src=rotatedImageURL;
</script>
</body>
</html>
I have been stuck here for a while, so any help is appreciated. Thanks in advance!
You likely need to wait until after drawing the image before calling toDataURL. The fireball is only drawn after the image is loaded but the rotate (and everything after that) is called right after registering the onload event handler (but before it has actually loaded).
I'm working on some code which is drawing to a canvas. One part of the code draws some lines onto the canvas. The position and colour of those lines don't change, but they often need to be redrawn because other code may have affected it (eg: drawn over the top of it).
There can be several hundred lines to draw, and in these cases, profiling shows me that it's taking ~200ms to draw, so I'm looking to optimise this somewhat.
One thing I noticed was that when drawing to the canvas, you basically are adding points to a path and then once ready, you can fill or stroke that path. Though the pixels on the canvas are out of date, if I were able to keep a reference to the path, then updating would be as simple as re-stroking the previously constructed path.
My question is: how on earth do you get a Path object?
The fill and stroke methods appear to accept a path object, and the spec defines the methods for Path, but I can't seem to find the actual Path class anywhere...
So, just to recap:
I have something like this:
function update() {
context.beginPath();
// lots of lines added to the default path...
context.moveTo(x1, y1); context.lineTo(somewhere, else);
context.moveTo(x2, y2); context.lineTo(somewhere, else);
context.stroke();
}
What I'd like is something like this:
function update() {
if (!this.path) {
this.path = new Path(); // <-- here's the magic
this.path.moveTo(x1, y2); this.path.lineTo(somewhere, else); // etc
}
this.path.stroke();
}
The canvas spec calls for a Path object that is not implemented in browsers yet.
BTW, when implemented, the Path object will be useful in hit-testing when combined with context.isPointInPath(myPath); Someday...
Here's how you could create your own Path object until the browsers catch up:
Create a JS object that contains a canvas where your path strokes are drawn.
When you want to do myPath.stroke(), use myVisibleContext.drawImage(myPath.context,0,0) to "blit" the path's canvas onto your drawing canvas.
Demo: http://jsfiddle.net/m1erickson/QLJv8/
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
function Path(maxWidth,maxHeight,color,linewidth,drawingContext){
this.width=maxWidth;
this.height=maxHeight;
this.drawingCtx=drawingContext;
this.points=[]
this.canvas=document.createElement("canvas");
this.canvas.width=maxWidth;
this.canvas.height=maxHeight;
this.ctx=this.canvas.getContext("2d");
this.ctx.strokeStyle=color;
this.ctx.lineWidth=linewidth;
this.lastX;
this.lastY;
}
Path.prototype.moveTo=function(x,y){
this.lastX=x;
this.lastY=y;
}
Path.prototype.lineTo=function(x,y){
this.ctx.moveTo(this.lastX,this.lastY);
this.ctx.lineTo(x,y);
this.ctx.stroke();
this.lastX=x;
this.lastY=y;
}
Path.prototype.stroke=function(){
this.drawingCtx.drawImage(this.canvas,0,0);
}
// create a new path object
var p=new Path(300,300,"blue",2,ctx);
// set the Path's drawing commands
p.moveTo(69,91);
p.lineTo(250,150);
p.moveTo(69,208);
p.lineTo(180,54);
p.lineTo(180,245);
p.lineTo(69,91);
p.moveTo(69,208);
p.lineTo(250,150);
// draw the Path.canvas to the drawing canvas
p.stroke();
// tests...
$("#stroke").click(function(){
p.stroke();
});
$("#erase").click(function(){
ctx.clearRect(0,0,canvas.width,canvas.height);
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="stroke">Path.stroke</button><br>
<button id="erase">Erase main canvas</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Turns out, it's just that no browser supports it yet, according to this blog (dated 24th January 2013) http://www.rgraph.net/blog/2013/january/html5-canvas-path-objects.html
Their is no path support in canvas, but why don't use svg line and set its zIndex to be on top of others.
None of the canvas drawing API let you hold references to objects.
Canvas lets you draw pixels in a bitmap, not create and manipulate objects like SVG does.
If you're looking to optimize performance and you want to reuse the same path over and over again, you might want to draw it once in a separate canvas oject, and then draw that canvas into your other canvas using drawImage (which can take a canvas as argument).
I have 2 canvases. One, the main canvas. Upon which all is drawn,
Second, the speech bubble canvas (balloon). Which displays information about specific regions on my main canvas upon client clicks.
I was playing around with my canvas after introducing the speech bubble and came across an issue.
This is a simple code that shows how the speech bubble is introduced:-
http://jsfiddle.net/m1erickson/AJvkN/
My canvas is a timeline, and is scrollable; has historical events plotted on it. Once a user clicks on an event a speech bubble appears.
Now what I don't want to happen is, when a client clicks on the canvas, a speech bubble appears and then scrolls, the speech bubble moves to a new position on the scrolled image, however still showing information about the previous location.
For this we have the hideballoon () which assigns css property left : -200. However this still causes inconsistencies. For example if I drag the canvas from left to right, the balloon doesn't disappear with the scroll, but reappears in a new position.
there is a .remove() function $("#balloon").remove()
http://api.jquery.com/remove/
This successfully removes the balloon however, the issue with this is:- it removes the balloon completely, and no future clicks will pop up any more speech bubbles. This is not what I want. I want something dynamic.
Click on event >> speech bubble appears >> scroll canvas >> speech bubble disappears >> click on canvas >> speech bubble pertaining to new click appears back >> and so on and so forth.
[Edited]
Use .show() and .hide() to keep the balloon out of your way when its not needed
When the user scrolls the window then just hide the balloon.
I assume you're scrolling the window instead of the canvas. If you're scrolling the canvas, just use $("#canvas").scroll( ... ) instead.
So when you need the balloon:
// move the balloon canvas to the target
$("#balloon").css({left:offsetX+X, top:offsetY+Y});
// and show it
$("#balloon").show();
And hide the balloon when the user clicks on it or when the window scrolls:
// listen for clicks on the balloon and then hide the balloon
$("#balloon").click(function(e){ $("#balloon").hide(); });
// listen for scrolls and then hide the balloon
$(window).scroll(function(e){
$("#balloon").hide();
});
Here’s working sample code and a Fiddle: http://jsfiddle.net/m1erickson/uWHkv/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ width:2000px; background-color: ivory; padding:10px;padding-top:100px; }
#canvas{border:1px solid red;}
#balloon{ position:absolute; left:-200px; }
</style>
<script>
$(function(){
// get reference to our drawing canvas
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// get reference to our balloon canvas
var balloon=document.getElementById("balloon");
var popCtx=balloon.getContext("2d");
// get the position of canvas relative to window
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
// define some targets and their basic info
var count=1;
var circles=[];
for(var x=50;x<1900;x+=50){
circles.push({
x:x, y:120, radius:20,
color:"blue",
info:"I'm #"+(count++)});
}
// draw the target circles on the canvas
ctx.fillStyle="yellow";
ctx.font="16px verdana";
for(var i=0;i<circles.length;i++){
drawCircle(circles[i]);
ctx.beginPath();
ctx.fillText(i+1,circles[i].x-8,circles[i].y+5);
}
// listen for clicks on the canvas and show the balloon
$("#canvas").click(function(e){
// get the mouseclick position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// account for the window scrolling
var scrollX=$(window).scrollLeft();
var scrollY=$(window).scrollTop();
// see if we clicked on any targets
for(var i=0;i<circles.length;i++){
var circle=circles[i];
var dx=(circle.x-scrollX)-mouseX;
var dy=(circle.y-scrollY)-mouseY;
var radius=circle.radius;
// true if we clicked in the target circle
if(dx*dx+dy*dy<=radius*radius){
drawBalloon(circles[i].x+radius,circles[i].y-100,circles[i].info);
}
}
});
// listen for clicks on the balloon and then hide the balloon
$("#balloon").click(function(e){ $("#balloon").hide(); });
// listen for scrolls and then hide the balloon
$(window).scroll(function(e){
$("#balloon").hide();
});
function drawCircle(circle){
ctx.save();
ctx.beginPath();
ctx.fillStyle=circle.color;
ctx.strokeStyle="black";
ctx.lineWidth=3;
ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
}
function drawBalloon(X,Y,theInfo){
popCtx.save();
popCtx.fillStyle="#FD0";
popCtx.strokeStyle="#000";
// draw the balloon
popCtx.beginPath();
popCtx.moveTo(52,02);
popCtx.quadraticCurveTo(02,02,02,42);
popCtx.quadraticCurveTo(02,77,27,77);
popCtx.quadraticCurveTo(27,102,07,102);
popCtx.quadraticCurveTo(37,102,42,77);
popCtx.quadraticCurveTo(102,77,102,42);
popCtx.quadraticCurveTo(102,02,52,02);
popCtx.lineWidth=3;
popCtx.stroke();
popCtx.fill();
// draw theInfo
popCtx.font="10pt arial";
popCtx.fillStyle="black";
popCtx.fillText(theInfo,10,50);
popCtx.restore();
// move the balloon canvas to the target
$("#balloon").css({left:offsetX+X, top:offsetY+Y});
$("#balloon").show();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=1950 height=300></canvas>
<canvas id="balloon" width=105 height=105></canvas>
</body>
</html>
Am newbie to html5. I want to include some mouse over function through css or javascript so that when i mouse over particular bar it has to display some message. I dont want to go for some api. pls help me out. Here is my code.
<!doctype html>
<html>
<head>
<script type="text/javascript">
window.onload=function(){
var canvas=document.getElementById('mycanvas');
var ctx=canvas.getContext('2d');
var value=[180,140,30,340,50,90];
var width=50;
var currx=30;
ctx.fillStyle="red";
var i = 0;
var interval = setInterval(function(){
if (i == value.length){
clearInterval(interval);
return;
}
var h=value[i];
ctx.fillRect(currx,canvas.height-h,width,h);
currx+=width+10;
i++;
}, 2000);console.log(interval);
};
</script>
</head>
<body>
<canvas id="mycanvas" height="400" width="400" style="border:1px solid #c3c3c3;">
</body>
</html>
Demo on jsFiddle
You have two options:
Use a library like KineticJS which abstracts the drawable shapes into objects and provides nifty methods for binding them to mouse events. This has the benefit of minimizing the work required by your side, therefore allowing you to concentrate on the functionality itself, and not reinventing the wheel.
Roll your own solution, much like someone does when he/she created a library like the one mentioned above. Design some abstraction for your shapes (in this instance some kind of a Bar object) that encompasses the relevant features (notably the x,y,w,h) and on canvas mousemove-event, bruteforce through all your bars and calculate whether or not the event mouse position is within a bar or not. Then act accordingly, e.g. redraw the bar in new color. Of course you'll have to handle mouseout as well (to color it back and the like).
Please help me:
create clickable regions in the canvas below that I can assign onmousedown= events to. I know how to do this with invisible DIVs, but I think there is a more elegant way to do it in canvas that I don't know.
when I click one of the regions, want to pass an image name to a function so that it changes the image being displayed to another image, and then changes it back onmouseup.
if you show me just one region and one mousedown/mouseup example I can do the rest...thanks.
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<canvas id="myCanvas" width="506" height="319" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=new Image();
img.onload = function(){
ctx.drawImage(img,0,0);
};
img.src="firstImage.gif";
</script>
/////////HERE NEED/////////
CREATE CLICKABLE REGION <region>
<region>
onmousedown=changeCanvasImage(secondImage.gif) //change image on click
onmouseup=changeCanvasImage(firstImage.gif) /change it back when done
</region>
</body>
</html>
The canvas element can fire events but graphical elements within the canvas cannot. To do this you'll either need to implement it yourself by detecting the position of the mouse on the canvas when it is clicked and relating the value to something in your canvas, or using one of the many canvas libraries available which will handle the detection for you.