I am trying to make an image masked by a png with a background image. It works fine when I put the masked image only but if I add a background image the front image is not masked anymore
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var bg = new Image();
var front = new Image();
var mask = new Image();
bg.src = 'img/background.jpg';
bg.onload = function() {
front.src = "img/tobemasked.jpg";
};
front.onload = function() {
mask.src = "img/mask.png";
}
mask.onload = function() {
display();
}
function display() {
context.drawImage(bg, 0, 0); // it works if i remove this line
context.drawImage(tmpMask, 0, 0);
context.globalCompositeOperation = "source-in";
context.drawImage(front, 0, 0);
}
</script>
I guess this is a quite common problem but I couldn't find anything related on the web.
Thank you for your help.
The "source-in" operation you are using to mask the front image is defined here http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#gcop-source-in like this:
Display the source image wherever both the source image and
destination image are opaque. Display transparency elsewhere.
Without drawing the background image, the destination image consists of only your mask and supposedly has transparent pixels. The front image will be displayed only where the mask is opaque. I understand that this is what you want.
However, after you have also drawn the background image, there are supposedly no transparent pixels in the destination image, it's totally opaque, and when you draw the front image, all parts of it will be displayed.
This would accomplish what I think you are trying to do:
context.drawImage(mask, 0, 0);
context.globalCompositeOperation = "source-in";
context.drawImage(front, 0, 0);
context.globalCompositeOperation = "destination-atop";
context.drawImage(bg, 0, 0);
The front image is masked first. After that there still are transparent pixels. The background image gets drawn on the transparent area with "destination-atop" option (see previous link).
I think that's the simplest method. Some other options are to use multiple canvas elements on top of each others to create layers or use some javascript library that makes it possible to use layers with canvas.
Related
I'm trying to put a image and text on background image using Canvas/jQuery, but i don't no how to do this. I need to do like this image http://static.catfly.com/quiz/which-friend-should-be-kidnapted-by-aliens/en/cover.jpg
I already tried and found some script for a blog but it's not complete script, it's only made a circle, anyone can help me please?
Here is my script below.
<body onload="displayImage()">
<script type="text/javascript">
//Global variables
var myImage = new Image(); // Create a new blank image.
// Load the image and display it.
function displayImage()
{
// Get the canvas element.
canvas = document.getElementById("myCanvas");
// Make sure you got it.
if (canvas.getContext)
{
// Specify 2d canvas type.
ctx = canvas.getContext("2d");
// When the image is loaded, draw it.
myImage.onload = function() {
// Load the image into the context.
ctx.drawImage(myImage, 0, 0);
// Get and modify the image data.
changeImage();
}
// Define the source of the image.
myImage.src = "https://pbs.twimg.com/profile_image/843519123711803393/pyYe9LFq_400x400.jpg";
}
}
function changeImage()
{
ctx.strokeStyle = "white";
ctx.lineWidth = "100";
ctx.beginPath();
ctx.arc(100, 100, 150, 0, Math.PI * 2, true);
ctx.closePath();
ctx.stroke();
}
</script>
<canvas id="myCanvas" width="200" height="200"></canvas>
</body>
One of the problems is that the canvas is only 200x200 and the line width of the circle is 100, and white, so when drawn it fills most of the canvas (it's also drawn slightly outside the canvas area in this case).
And, the image in question also has a load error which may be the primary cause here (onerror+onabort handlers should always be added).
Simply adjust down the line width, fix the image, and I would also recommend setting the canvas bigger (it can be set using the image size).
Currently I have this code:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'assets/img/img.png';
This load an image inside my canvas. After that I have a code which draws some graphics on the image.
Currently I have scaled the image file to be with the size of the canvas. But I would like to have it in much higher resolution like it was originally and to be able to draw on the original one. But show the final image scaled inside the canvas window. How can I achieve that?
I'm using Paper.js to draw lines on canvas.
I want to be able to upload local image to the paperjs canvas and then be able to draw on top of it.
What I did is:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
function make_base()
{
var img = document.createElement("img");
img.src = "http://paperjs.org/tutorials/images/working-with-rasters/mona.jpg";
context.drawImage(img, 100, 100);
}
document.getElementById('imageUpload').addEventListener('click', function(){
make_base();
});
This successfully adds an image to my canvas, but when I draw on canvas, image disappears and the image is on top of the lines, should be behind them.
You can add the image to the paper project as a paperjs Raster item, as such
var raster = new Raster({
source: "http://paperjs.org/tutorials/images/working-with-rasters/mona.jpg",
position: view.center
});
It will be inserted into the project in the current layer. You can then use paperjs functions like sendToBack and bringToFront to manipulate what appears where. I would probably put the raster image on the first Layer then add a new Layer for the drawing to make it easy to keep track of.
If you don't need to change or working with the image, use background-image on canvas tag:
<canvas id="canvas"
style="background-image: url(http://paperjs.org/tutorials/images/working-with-rasters/mona.jpg);"></canvas>
Would it be possible to fill a png with transparency with a pattern (a repeatable texture)?
Here's a quick example of loading an image onto the canvas, just not sure how to fill it with a pattern, if that isn't possible then would there be a way to extract a path from the png?
<script>
var c = document.getElementById("a");
var ctx = c.getContext("2d");
var test= new Image();
test.src = "images/test.png";
test.onload = function() {
ctx.drawImage(test, 0, 0);
};
</script>
<body>
<canvas id="a"></canvas>
</body>
I've also created a jsfiddle with an actual loaded png
This is the effect I'm looking to achieve
Update
working example based on Simon Sarris' answer
http://jsfiddle.net/sergeh/G8egW/6/
First, draw the image to Canvas.
Then do globalCompositeOperation = 'source-in';
Then draw the pattern. It will only exist where the image was.
http://jsfiddle.net/G8egW/2/
If you had stuff already on the canvas before this time, you'll need to do the above operations on an in-memory canvas and then draw that canvas to your normal canvas. Like this:
http://jsfiddle.net/G8egW/5/
(notice the difference in the grid)
How do I merge a smaller image on top of a larger background image on one canvas. The smaller image will move around. So I will need to keep reference of the original background pixel data, so that the each frame the canvas can be redrawn, with the overlay in its new position.
BgImage: 1280 x 400, overlayImage: 320 x 400, overlayOffsetX: mouseX
I think it is common to draw whole scene each time you want to change something, so:
context.drawImage(bgImage, 0, 0);
context.drawImage(overlayImage, overlayOffsetX, 0);
UPDATE
You could manually compose image data of two images with making copy of background image data
or
do something easier, probably faster. You could create new canvas element (without attaching to the document) which would store image data in easy to manage form. putImageData is good if you want to place rectangular image into the canvas. But if you want to put image with transparency, additional canvas will help. See if example below is satisfying you.
// preparation of canvas containing data of overlayImage
var OVERLAY_IMAGE_WIDTH = 320;
var OVERLAY_IMAGE_Height = 400;
var overlayImageCanvas = document.createElement('canvas');
overlayImageCanvas.width = OVERLAY_IMAGE_WIDTH;
overlayImageCanvas.height = OVERLAY_IMAGE_HEIGHT;
overlayImageCanvas.getContext('2d').putImageData(overlayImage, 0, 0);
// drawing scene, execute this block every time overlayOffsetX has changed
context.putImageData(bgImage, 0, 0);
context.drawImage(overlayImageCanvas, overlayOffsetX, 0);