Set the background in canvas using layer (zIndex) - javascript

I need to get a background on canvas using layers. Variable for it's background. I know I should use CSS and set the z-index, but do not know how to do it in this case.
JS:
function doFirst(){
var x = document.getElementById('canvas');
canvas = x.getContext('2d');
var item1 = new Image();
item1.src = "images/sheep.png";
item1.addEventListener("load", function() { canvas.drawImage(item1,20,300)}, false);
var item2 = new Image();
item2.src = "images/tshirt.png";
item2.addEventListener("load", function() { canvas.drawImage(item2,300,300)}, false);
var background = new Image();
background.src = "images/background.png";
background.addEventListener("load", function() { canvas.drawImage(background,0,0,1024,768)}, false);
}
HTML:
<canvas id="canvas" width="1024" height="768">

The Canvas element is not designed to address layers within the element, you'll need to approach your problem using multiple canvas elements instead.
Here's a good article to assist you with the approach

If you're wanting to display multiple images on the same layer (canvas) then to order the images just draw them to the screen in the order you want them to display. The first drawn images will be at the bottom with each draw drawing on top.
If you want to treat layers as individual canvases, you can use css to set the z-index, or use Javascript like so:
canvas.style.zIndex = 99;

Related

How to get reference to the particular image on canvas on mouse click?

The situation is : I have to draw an image on canvas dynamically.
The code is :
HTML :
<canvas id="canvas" width="500px" height="300px"></canvas>
<input type="file" id="file-input">
jquery :
$(function() {
$('#file-input').change(function(e) {
var file = e.target.files[0],
imageType = /image.*/;
if (!file.type.match(imageType))
return;
var reader = new FileReader();
reader.onload = fileOnload;
reader.readAsDataURL(file);
});
function fileOnload(e) {
var $img = $('<img>', { src: e.target.result });
var canvas = $('#canvas')[0];
var context = canvas.getContext('2d');
$img.load(function() {
context.drawImage(this, 0, 0);
});
}
});
It adds the image to the top left corner. But now I might need to shift the image to another position by dragging and dropping. Also, I need to resize the image in similar way. For that I need to select the image (by getting reference to that image) on mouse click. I could have done that by checking if the mouse click coordinates overlaps with any image area. But if there are large number of images, this way will be inefficient (storing images in array and checking with each of them). Is there any more efficient way ?
PS : I am trying to build a UI designer which generates UI by dragging and dropping the elements in angular. I just started with the image element.
Edit 1 - I could use Fabric.js canvas instead. But still I would like to know if this can be done on native canvas too.

Copying and pasting one canvas inside another canvas's corner

I have two canvases on my HTML page and what i actually want to do is pasting all stuff inside first canvas in bottom right corner of second canvas.
This is the code I was trying:
<canvas id="first"></canvas>
<canvas id="second"></canvas>
<script>
var first = document.getElementById('first').getContext('2d');
var sec = document.getElementById('second').getContext('2d');
//--code for drawing in first canvas--
var img = new Image();
img.src="imgName.jpg";
img.onload = function() {
sec.drawImage(img,0,0,sec.canvas.width,sec.canvas.height);
//Actually i want first canvas to overlap image on second canvas
var paste = new Image();
paste.src = first.canvas;
paste.onload = function() {
sec.drawImage(paste,100,100,400,600);
};
};
</script>
Problem is: second canvas shows image but doesn't shows first canvas in its bottom right corner.
Please worthy guys, i need the answer. Its very Important. Thanks in advnce to all helpers..
The way you are drawing the first canvas on the second one is not correct. You can directly draw a canvas on another canvas using drawImage() method.
var first = document.getElementById('first').getContext('2d');
var sec = document.getElementById('second').getContext('2d');
// draw on first canvas
first.fillStyle = '#07C';
first.fillRect(0, 0, first.canvas.width, first.canvas.height);
// draw image on second canvas
var img = new Image();
img.src = "http://lorempixel.com/300/300";
img.onload = function() {
sec.drawImage(img, 0, 0, sec.canvas.width, sec.canvas.height);
sec.drawImage(first.canvas, 100, 100, 100, 100); // draw first canvas on a portion of second canvas
};
body {display: flex}
<canvas id="first" width="200" height="200"></canvas>
<canvas id="second" width="200" height="200"></canvas>

Give height to the image object using javascript is not working

I am trying to give height to an image object using javascript, But its not working.
html code
<canvas id="canvas1" height="500px" width="500px">
</canvas>
I want to create background image using javascript and this image must be set according to canvas size.
Javascript code:
canvas = document.getElementById("canvas1");
c = canvas.getContext("2d");
var bg = new Image();
bg.src = "images/bg.png";
bg.height = "100";
bg.width = "100";
c.drawImage(bg,0,0);
I can see the image but can not give the height and width of that image at run time.
How can i give the height and width of image object at runtime.?
Thank you in advance for your help.
There are a few issues in the code:
Issue 1
The first one being the tag attributes. Doesn't really affect the result but the correct syntax is an integer value without px at the end as width and height for canvas can only use pixels:
<canvas id="canvas1" height="500" width="500"></canvas>
Issue 2
The next issue is that you try to set read-only properties on the image element:
var bg = new Image();
bg.src = "images/bg.png";
//bg.height = "100"; invalid
//bg.width = "100"; invalid
You don't really need to set the image size; you can if you absolutely want by using this syntax (then get actual size using naturalWidth / naturalHeight if you should need them later - the full image will be loaded in any case):
var bg = new Image(width, height);
But you can simply use width and height with the drawImage() method (see below).
Issue 3
The third issue is that you don't allow the image to load. Image loading is asynchronous so you need to add an onload handler:
var bg = new Image();
bg.onload = done; /// wait for image to load, then call done()
bg.src = "images/bg.png";
function done() {
c.drawImage(bg,0,0);
/// continue here
}
Optionally define the destination size like this:
function done() {
c.drawImage(bg,0,0, width, height); /// the size you want
/// continue here
}
If you want to fill the canvas use:
c.drawImage(bg,0,0, canvas.width, canvas.height);
Hope this helps!
Since it's on a canvas you need to set them in the drawimage function
canvas = document.getElementById("canvas1");
c = canvas.getContext("2d");
var bg = new Image();
bg.src = "images/bg.png";
c.drawImage(bg,0,0, 100, 100);

Replacing divs with background images with canvas elements

I am trying to replace any divs that have background images with canvas elements with those background images drawn onto them.
I've got the basics working but I am slightly stumped by the difference in image quality between the background-image on a div and the same image drawn onto a canvas.
Here is the code I am using to do this:
$('#container div').each(function(){
if($(this).css('background-image') != 'none'){
var bgImage = $(this).css('background-image').replace(/^url|[\(\)]/g, '');
var image = new Image();
var attrs = $(this)[0].attributes;
var dimensions = new Array();
var canvas = document.createElement('canvas');
dimensions.push($(this).height())
dimensions.push($(this).width());
$(canvas).attr('width',dimensions[0]);
$(canvas).attr('height',dimensions[1]);
$(canvas).css('background-image', 'none');
for(var i = 0; i < attrs.length; i++){
$(canvas).attr(attrs[i].nodeName,attrs[i].nodeValue);
}
var ctx = canvas.getContext('2d');
image.onload = function () {
ctx.drawImage(image, 0, 0, image.height, image.width);
}
image.src = bgImage;
$(this).replaceWith(canvas);
}
});
Here are the results:
It looks like the image is being stretched for some reason but I've tried to console.log the width/height of the image that I am using in drawImage and the values match up to the image dimensions. The results show just a crop of the image - the real one is 900x4000ish pixels.
Here is a jsfiddle link showing the problem in action:
http://jsfiddle.net/xRKJt/
What is causing this odd behaviour?
Ha! (took some seconds to figure out)
Image has naturalWidth and naturalHeight attributes which reflect its pixel dimensions. Change your code
image.onload = function () {
ctx.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight);
}
Because the image is so large, if you open the image in the browser it zooms out it by default. I think you'll get those zoomed out width and height attributes if you try to access image.width and image.height. Or something along the lines.

Removing an image from a canvas in HTML5

there's an example, which loads 2 images:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img1 = new Image();
img.src = "/path/to/image/img1.png";
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
var img2 = new Image();
img2.src = "/path/to/image/img2.png";
img2.onload = function() {
ctx.drawImage(img2, 100, 100);
};
I need to remove(replace) img2 from canvas. What is the best way to do it?
I think maybe you misunderstand what a Canvas is.
A canvas is essentially a 2 dimensional grid of pixels along an 'X' axis and a 'Y' axis. You use the API to draw pixels onto that canvas, so when you draw an image you're basically drawing the pixels that make up that image onto your canvas. The reason there is NO method that lets you just remove an image, is because the Canvas doesn't know there's an image there in the first place, it just see pixels.
This is unlike the HTML DOM (Document Object Model) where everything is a HTML element, or an actual 'thing' you can interact with, hook-up script events to etc. this isn't the case with stuff you draw onto a Canvas. When draw a 'thing' onto a Canvas, that thing doesn't become something you can target or hook into, it's just pixels. To get a 'thing' you need to represent your 'thing' in some way such as a JavaScript object, and maintain a collection of these JS objects somewhere. This how how Canvas games work. This lack of a DOM-like structure for Canvas makes rendering very fast, but can be a pain for implementing UI elements that you can easily hook into and interact with, remove etc. For that you might want to try SVG.
To answer your question, simply paint a rectangle onto your Canvas that covers up your image by using the same X/Y coords and dimensions you used for your original image, or try Pointy's solution. 'Cover-up' is probably the wrong terminology, since you're actually replacing the pixels (there are no layers in Canvas).
It's not clear what you want the canvas to show when the image is gone. If you want it to be transparent, you could get the image data and fill it with transparent pixels:
var img = ctx.createImageData(w, h);
for (var i = img.data.length; --i >= 0; )
img.data[i] = 0;
ctx.putImageData(img, 100, 100);
where "w" and "h" would be the width and height of your original image.
edit — if you just want another image there, why not just put one there? It will overwrite whatever pixels are there on the canvas.
You can use clearRect() function to clear the image area.Rather then clearing whole context you can clear only the image area using this:
ctx.clearRect(xcoordinate_of_img1,ycoordinate_of_img1,xcoordinate_of_img1 + img1.width ,ycoord_of_img1 +img1.height );
If what "Sunday Ironfoot" said is right, then the best way to remove an image is by drawing the images once again from scratch. For this, you need to have an array of images and draw only the ones you use. For example,
function EmptyClass{};
var img=new Array();
img[0]=new EmptyClass;
img[0].i=new Image();
img[0].src="yourfile1.jpg";
img[0].enabled=true;
img[1]=new EmptyClass;
img[1].i=new Image();
img[1].src="yourfile2.jpg";
img[1].enabled=false;// <-------- not enabled, should not be drawn equivalent to removing
img[2]=new EmptyClass;
img[2].i=new Image();
img[2].src="yourfile3.jpg";
img[2].enabled=true;
for(var i=0;i<3;i++){
if(img[i].enabled)ctx.drawImage(img[i], 100, 100);
}
P.S. I am creating an engine for javascript canvas. Will post it within a week
Peace
You can erase an image by drawing the same image again, using a different globalCompositeOperation
ctx.globalCompositeOperation ="xor"
ctx.drawImage(img2, 100, 100);
See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
Unlike drawing things yourself, if you 'replace' THE image on a canvas, the old one is still there.
Canvas c2;
...
if (null != Image2) {
var ctx = c2.getContext("2d");
ctx.clearRect(0, 0, c2.width, c2.height);
}
Can you overlay canvas objects (I guess I should try before asking, you can -1 one me for being lazy). I guess I'd be interested in have one canvas element as a background, and then another for a layer objects that pop in and out of view. Might be a little more efficient then having to redraw every image if one gets deleted or moved. I'll play around and see what I can find.
There is ``ctx.clearRect(x, y, w, h)'' but this is not a good way to remove the shape, because it will remove any full or partial shapes in the same area of the removed shape. This shouldn't happen, and may remove one or more shapes, I've found it's best to save all your shapes in a list that usually comes from the database using backend language or ajax request, and add for it's shape object an identifier, when you need to remove a shape just remove that shape from the list using the id or the index, then Redraw the canvas with this new array of shapes without a deleted shape, the next time the page loads, this shape will not be added to this list, because it should be deleted from database.
const projectStamps = [{image_id: 'scream', x: 100, y: 100, id: 1}, {image_id: 'scream', x: 100, y: 100, id: 2}, {image_id: 'scream', x: 50, y: 0, id: 3}, {image_id: 'scream', x: 150, y: 0, id: 4}];
let currentShapes = [];
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
function validStampObj(stamp){
if (typeof(stamp.x) !== 'number' || typeof(stamp.y) !== 'number' || typeof(stamp.image_id) === 'undefined' || !document.getElementById(stamp.image_id)){
return false;
} else {
return true;
}
}
function addStamp(stamp){
if (!validStampObj(stamp)){
console.log("can not add stamp, invalid object");
return false;
}
const image = document.getElementById(stamp.image_id);
stamp['w'] = image.getBoundingClientRect().width;
stamp['h'] = image.getBoundingClientRect().height;
ctx.drawImage(image, stamp.x, stamp.y, stamp.w, stamp.h);
currentShapes.push(stamp);
return stamp;
}
let id = 1;
window.onload = function() {
drawProject();
};
function clearCanvas(){
currentShapes = [];
ctx.clearRect(0, 0, canvas.width, canvas.height);
return true;
}
const projectImage = document.getElementById("project_image");
function drawProject(){
if (!projectImage){console.log('missing project image element');return false;}
clearCanvas();
ctx.drawImage(projectImage,0,0);
projectStamps.forEach( (stamp)=>{
addStamp(stamp);
});
}
function removeStamp(targetId){
let targetI = false;
for (let i=0; i<projectStamps.length; i++){
if (projectStamps[i].id == targetId){
targetI = i;
break;
}
}
if (targetI !== false){
/* remove the stamp from drawing stamps list and redraw the data */
projectStamps.splice(targetI,1);
drawProject();
}
}
setTimeout( ()=>{
removeStamp(3);
console.log("removed icon with id 3");
}, 2500 );
<p>Image to use:</p>
<img id="scream" width="35" height="35"
src="https://i.ibb.co/wYyc259/iconimage.png" alt="The Scream">
<img id="project_image" width="450" height="300"
src="https://i.ibb.co/sK5HtQy/bulding-image.png" style="position:absolute;left:-15455px;">
<p>Canvas:</p>
<button onclick="drawProject()">Redraw things</button>
<canvas id="myCanvas" width="450" height="300"
style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
notes if you used clearRect in this example it will remove the part of main image of the canvas not just the icon with id 3 like this code does hope it helps.

Categories