I need to find a way to change the picture when the user clicks on it, I seem to be having problems.
heres my code:
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var img = new Image();
img.src = 'Birthday.jpg';
img.onload = function() {
context.drawImage(img, 47, 90, 200, 300);
};
}
Ive already tried things like:
img.onclick = function() {
context.clearRect(47, 90, 200, 300);
img2.src = 'BirthdayOUT.jpg';
context.drawImage(img2, 47, 90, 200, 300);
};
When you paint an image to the canvas you do not paint the image element itself, just a bitmap representation.
This means that the img.onclick will never fire. Instead, you must manually keep track of where you drew the image and use a canvas onclick, determine if you clicked on the image, and then change the draw the new image.
you should create your img.onload function before you set the src, if not the onload may never fire.
I'm not sure what you're trying to achieve here but if you just want to have an image on the page, don't use the 'canvas' and change the image via the 'src' property.
However, if you want to have this on a canvas - which I suspect - you have to store the coordinates/dimensions of the image when it is drawn. Then, to change the picture, use 'clearRect()' to blank that area and draw the new image.
Note that in your code, the 'img' is not passed to the canvas as an element, but as a bitmap, as mentioned by 'Simon Sarris'. That means, your handler for the 'onclick' event must be assigned to the canvas. Then check whether the click occourred within the borders of the image. to achieve that, you need to access 'clientX' and 'clientY' from the event object which declare the position of the mouse click relative to the client area. Make sure to keep your img coordinates relative to the client area too.
Javascript:
window.onload = init;
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var img = new Image();
function init(){
img.src = 'Birthday.jpg';
context.drawImage(img, /* your img coords */ );
canvas.addEventListener('click', onCanvasClick);
}
function onCanvasClick(event){
var clickX = event.clientX;
var clickY = event.clientY;
if ( clickX > imgLeft && clickX < imgRight && clickY > imgTop && clickY < imgBottom ){ changePicture(); }
}
function changePicture(){
context.clearRect( /* your img coords */ );
img.src = /* new img URL */;
// save new img coords before next step
context.drawImage(img, /* your new img coords */ );
}
Image coordinates called 'imgLeft', 'ImgRight', 'ImgTop', 'imgBottom' / relative to client area!
You may have to modify the function name in 'addEventListener()', I'm not entirely sure. Maybe put the following:
canvas.addEventListener('click', function(){ onCanvasClick(); });
Your problem is not the clearing of the canvas, but the click event handling.
The img.onclick is not firing because the picture on the canvas is not an Image object. See this as an example.
Related
I load a picture and draw it on canvas. With the mouse I can draw on the picture. Now I want to copy a defined part of an another picture to the same part of the shown picture. I thought I can copy the pixels from img2 to img1. Another idea is to place the pictures on top of the other (img1 oder img2) and cut an area from img1.
I don't know what is a possible way.
My try:
function loadPic() {
var ctx2 = document.getElementById('can').getContext('2d');
img = new Image();
img2 = new Image();
img.onload = function() {
ctx2.drawImage(img,0,0);
}
img.src = 'Haut vorne m.bmp';
img2.src = 'Muskeln vorne m.bmp';
}
And the copy:
var g = img2.getImageData(262, 157, 200, 200);
ctx.putImageData(g, 55, 170);
I get an error: img2.getImageData is not a function
Can anybody help ?
Thank you !
getImageData() is a function of canvas, not of Image. See here.
Replace img2.getImageData(...) with ctx.getImageData(...) or ctx2 if that's what you have.
I am working with a single canvas that allows the user to click on a window pane in a window image. The idea is to show where the user has clicked. The image will then be modified (by drawing a grill on the window) and then saved to in JPEG. I am saving the canvas image prior to the click function because I don't want the selection box to show in the final image. However, Firefox often displays a blank canvas when restoring the canvas where IE and Chrome do not. This works perfectly in Chrome and IE. Any suggestions? Does Firefox have a problem with toDataURL()? Maybe some async issue going on here? I am also aware that saving a canvas in this fashion is memory intensive and there may be a better way to do this but I'm working with what I have.
Code:
/**
* Restores canvas from drawingView.canvasRestorePoint if there are any restores saved
*/
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.src = drawingView.canvasRestorePoint.pop();
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
}
},
/**
* Pushes canvas into drawingView.canvasRestorePoint
*/
saveCanvas:function()
{
var canvas = document.getElementById("drawPop.canvasOne");
var urlData = canvas.toDataURL();
drawingView.canvasRestorePoint.push(urlData);
},
EXAMPLE OF USE:
readGrillInputs:function()
{
var glassNum = ir.get("drawPop.grillGlassNum").value;
var panelNum = ir.get("drawPop.grillPanelNum").value;
drawingView.restoreCanvas();
drawEngine.drawGrill(glassNum, panelNum,null);
drawingView.saveCanvas();
},
sortClick:function(event)
{
..... //Sorts where user has clicked and generates panel/glass num
.....
drawingView.showClick(panelNum, glassNum);
},
showClick:function(panelNum, glassNum)
{
var glass = item.panels[panelNum].glasses[glassNum];
var c = drawEngine.context;
drawingView.restoreCanvas();
drawingView.saveCanvas();
c.strokeStyle = "red";
c.strokeRect(glass.x, glass.y, glass.w, glass.h);
},
By just looking at the code setting the img.src is an async action to retrieve the image, so when you try to draw it 2 lines later to the canvas, it probably hasn't been loaded yet (having it in cache will make it return fast enough that it might work).
You should instead use an img.onload function to draw the image when it has loaded.
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.onload = function() {
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
};
img.src = drawingView.canvasRestorePoint.pop();
}
},
Allright, this is going to be quite hard to explain but I will try to explain my problem as clear as possible.
I currently have a HTML5 Canvas with a couple of preloaded shapes which I changed to images. I am using a modified version of this example. On the canvas I have now I can drag, drop and select the shapes which are preloaded.
I have implemented an option to upload a new image to the canvas using this:
var imageLoader = document.getElementById('uploader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext('2d');
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var imgNew = new Image();
imgNew.onload = function(){
ctx.drawImage(imgNew, 0, 0);
}
imgNew.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
This will now just put an image in the top-left corner of the canvas and when I select another shape this image will disappear. All shapes that are already in the canvas are in an array called 'shapes'. In the example there is an option to add a new shape when you dubbelclick on the canvas, this is the code:
// double click for making new shapes
canvas.addEventListener('dblclick', function(e) {
var mouse = myState.getMouse(e);
myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
}, true);
This is the addShape part which is called when double clicking:
CanvasState.prototype.addShape = function(shape) {
this.shapes.push(shape);
this.valid = false;
}
What I am trying to do is when I upload an image using the file upload the image should be added to the 'shapes' array so I can also drag,drop and select the uploaded image. (basically I need to do the same with the uploaded image as I can do with the preloaded ones) My guess is that it should be done something like the doubleclick method and addShape but I can't get this to work.
A working version of my current version can be found here:
http://codepen.io/anon/pen/qLuCy/
If anyone knows how I can get this to work it would be great!
first the result, here : http://codepen.io/anon/pen/qBmnC/
Your shape object can only draw one single hard-coded image, so change this and have shape be either a color or an image. In fact for this you just have to change shape.draw since the 'type' of the fill does not matter in the constructor.
So just test the fill and draw accordingly :
// Tekent de Shape
Shape.prototype.draw = function(ctx) {
var locx = this.x;
var locy = this.y;
var fill = this.fill ;
if (typeof fill == 'string' )
{
ctx.fillStyle = fill;
ctx.fillRect(locx, locy, this.w, this.h);
}
else
{
ctx.drawImage(fill, locx, locy, this.w, this.h);
}
}
then on image load i just add a shape that has this image as fill :
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var imgNew = new Image();
imgNew.onload = function(){
s.addShape(new Shape(60,60,imgNew.width,imgNew.height,imgNew));
}
imgNew.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
I had to put the shape collection, s, as a global var.
You can also see that i used the same scheme in init() to
add an image once it's loaded.
After being a long time lurker, this is my first post here! I've been RTFMing and searching everywhere for an answer to this question to no avail. I will try to be as informative as I can, hope you could help me.
This code is for my personal webpage.
I am trying to implement some sort of a modern click-map using HTML5 and jQuery.
In the website you would see the main image and a hidden canvas with the same size at the same coordinates with this picture drawn into it.
When the mouse hovers the main picture, it read the mouse pixel data (array of r,g,b,alpha) from the image drawn onto the canvas. When it sees the pixel color is black (in my case I only check the RED value, which in a black pixel would be 0) it knows the activate the relevant button.
(Originally, I got the idea from this article)
The reason I chose this method, is for the page to be responsive and dynamically change to fit different monitors and mobile devices. To achieve this, I call the DrawCanvas function every time the screen is re-sized, to redraw the canvas with the new dimensions.
Generally, this works OK. The thing is ,there seems to be an inconsistent behavior in Chrome and IE(9). When I initially open the page, I sometimes get no pixel data (0,0,0,0), until i re-size the browser. At first I figured there's some loading issues that are making this happen so I tried to hack it with setTimeout, it still doesn't work. I also tried to trigger the re-size event and call the drawCanvas function at document.ready, still didn't work.
What's bothering me is most, are the inconsistencies. Sometimes it works, sometimes is doesn't. Generally, it is more stable in chrome than in IE(9).
Here is the deprecated code:
<script type="text/javascript">
$(document).ready(function(){setTimeout(function() {
// Get main image object
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
// Create a hidden canvas the same size as the main image and append it to main div
var canvas = document.createElement('canvas');
canvas.height = mapWrapper.clientHeight;
canvas.width = mapWrapper.clientWidth;
canvas.fillStyle = 'rgb(255,255,255)';
canvas.style.display = 'none';
canvas.id = 'hiddencvs';
$('#map_wrapper').append(canvas);
// Draw the buttons image into the canvas
drawCanvas(null);
$("#map_wrapper").mousemove(function(e){
var canvas = document.getElementById('hiddencvs');
var context = canvas.getContext('2d');
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
// Get pixel information array (red, green, blue, alpha)
var pixel = context.getImageData(x,y,1,1).data;
var red = pixel[0];
var main_img = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
if (red == 0)
{
...
}
else {
...
}
});
},3000);}); // End DOM Ready
function drawCanvas(e)
{
// Get context of hidden convas and set size according to main image
var cvs = document.getElementById('hiddencvs');
var ctx = cvs.getContext('2d');
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
cvs.width = mapWrapper.clientWidth;
cvs.height = mapWrapper.clientHeight;
// Create img element for buttons image
var img = document.createElement("img");
img.src = "img/main-page-buttons.png";
// Draw buttons image inside hidden canvas, strech it to canvas size
ctx.drawImage(img, 0, 0,cvs.width,cvs.height);
}
$(window).resize(function(e){
drawCanvas(e);
}
);
function findPos(obj)
{
...
}
</script>
I'd appreciate any help!
Thanks!
Ron.
You don't wait for the image to be loaded so, depending on the cache, you may draw an image or not in the canvas.
You should do this :
$(function(){
var img = document.createElement("img");
img.onload = function() {
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
...
// your whole code here !
...
}
img.src = "img/main-page-buttons.png";
});
I have two images inside a <canvas> element.
var ctx = document.getElementById('canvas').getContext('2d');
var img1 = new Image();
img1.src = 'cloud.jpg';
img1.name = "Image 1";
img1.onload = function() {
ctx.drawImage(img1, 0, 0);
};
var img2 = new Image();
img2.src = 'eleph.png';
img2.name = "Image 2";
img2.onload = function() {
ctx.drawImage(img2, 250, 250);
};
Now, when User clicks inside canvas, I want to find which object was clicked.
For example, alert img1.name or img2.name when user clicks corresponding image inside the canvas.
Please give some directions as how to do this. Thanks!
First of all, you must have stored in some variable the position and size of each image. After that, add an onclick handler on you canvas element that iterate over the image position collection checking which one is under the mouse on the click event.