Adding mask layer over fabric.js canvas - javascript

I have a problem that I'd like to add round mask on top of the editable fabric.js HTML5 canvas.
Similar problem is described in this article:
Creating an Image Mask with HTML 5 Canvas
My problem is that when I add this layer on top of the fabric.js canvas then my canvas is not editable any more inside this transparent circle. This means that the top element (the mask) captures the click/drag event, but I'd like to move the items under this mask element. Looking for ideas, how to work around this problem.

You can utilize built-in support for masks in fabric.
Here's an example of creating a circular mask at 100/100 with the radius of 200:
var canvas = new fabric.Canvas('...');
// ...
canvas.clipTo = function (ctx) {
ctx.arc(100, 100, 200, 0, Math.PI*2, true);
};

Related

javascript - How to clip using drawImage/putImageData

I'm writing an application that needs static clipping for images on the canvas (as you move the images on the canvas the clipping area stays in one place). I have three cases: polygon, ellipse, any shape specified with an image. I was able to cope with polygon and ellipse, because I can do them with paths and arcs, but when it comes to a mask specified via an image I'm not sure what to do.
Example shape to clip to:
Let's say I am not able to draw it using paths
So I have it specified with an image, I know how to obtain image data from it. What I'm trying to achieve is to clip everything that is out of that figure.
I was trying like this:
canvas.clipTo = function (ctx) {
ctx.drawImage(shape.src, left, top);
};
And like this:
canvas.clipTo = function (ctx) {
ctx.putImageData(imgData, left, top);
};
Of course none of them work as I expect, it just draws that black shape instead of clipping to that region.
Any ideas how to do it?
I do it by creating a new canvas the same size as the mask image. Then draw the image on that canvas, then set the ctx.globalCompositeOperation to "destination-in" draw the mask over the image (masking it) , then draw the that canvas to the on-screen canvas with ctx.drawImage
As this is most definitely a duplicated question I will not give the answer as code, it's been done to death here on stackoverflow.
Oh and I forgot. Using imageData to clip is a very inefficient way to do it.

Skew the drawing horizontally and vertically in html5 canvas using mouse

In my code I am loading images to canvas element. Then I need to drag, resize, rotate and skew it. I managed to implement both dragging and resizing. How can I implement skew using mouse on this code? I read a helpful article on this subject (http://www.subshell.com/en/subshell/blog/image-manipulation-html5-canvas102.html). I found fabricjs plugin, but it work only one image and without drag. For example: http://fabricjs.com/matrix-transformation/ .
If you will use the transform function:
ctx.transform(1, 0.5, -0.5, 1.2, 30, 60);
This will transform all image objects assigned to the canvas element. I would like only the selected image.
My code:
https://jsfiddle.net/sjLnqk5d/2/
Here's an updated fiddle that allows you to skew any image individually by pressing Shift when clicking one of the corner handles. You may need to tweak it a little bit to have the movements appear a bit more intuitive.
The trick is indeed in using ctx.save() and ctx.restore() around the ctx.transform() call, which makes sure that the transformation (and any other property changes) only applies between the save and restore.
Here are the key changes:
Shape.prototype.draw:
...
var skewX = this.skewX;
var skewY = this.skewY;
imgNew.onload = function(){
ctx.save();
ctx.transform(1, skewX/100, skewY/100, 1, 0, 0);
ctx.drawImage(imgNew, locx, locy, width, height);
ctx.restore();
}

How to clear rectangle on Image in Canvas

I need to clear a rectangle Drawn on Image in Canvas with out damage existing image. I can draw small rectangle points and clear that out. But the problem is when I clear rectangle it remains as white small patch on image.
Can someone tell me how to clear a rectangle on image without damage the existing image.
I have used following methods to clear rectangles but didn't work.
1) context.fillStyle ="white";
2) context.clearRect(xCoordinate, yCoordinate, 10, 08);
Thanks in advance!
Canvas doesn't work that way. It's a single layer, its also transparent by default. So with that in mind, you might be able to achieve what you want by simply giving the canvas element a CSS background. That way anything you draw on top of that background can easily be removed and the background will show through.
#backed-canvas{
background-image: url(http://www.placebear.com/300/200);
}
JSFiddle example: https://jsfiddle.net/yLf5erut/
There is one thing you can do.
When create a rectangle on the canvas just get the image data like:
var imgData = context.getImageData(xCoordinate, yCoordinate, 10, 8);
and draw the rectangle.
When clearing out the rectangle just place then image data back like this:
context.putImageData(imgData, xCoordinate, yCoordinate);
I suggest using 2 canvas elements one over another.
So you can have the original image drawn on the bottom canvas with low zIndex, and the top one with highter zIndex can be used to draw / clear whatever needed. This is a common practice, and for more complecated animations you will end up with better performance.

fabric.js: move clipped Image behind fixed clipping-mask

I'm working on a small script that lets a user load a custom image into the canvas on the webpage. So far that works pretty neat. The canvas is initialized using the fabric.js script in order to let the user do some easy editing tasks.
The "uploaded" image is clipped by a simple rectangle. Now comes the tricky part: the user should then be able to move around, scale and rotate the image, whilst the rectangle stays in place; selecting the image section preferred. However, even
lockMovement = true;
or
lockMovementX = true;
lockMovementY = true;
do not keep that clipping mask in place. Any other way to achieve this?
Any help is greatly appreciated! Please find a demo here: http://jsfiddle.net/efmbrm4v/
I had the same problem and I solved it with following code:
image.clipTo = function (ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0); // Reset transformation to default for canvas
ctx.rect(
100, 100, // Just x, y position starting from top left corner of canvas
200, 200 // Width and height of clipping rect
);
ctx.restore();
};
You can try it out here: http://jsfiddle.net/Jagi/efmbrm4v/1/

HTML5/Javascript - How to get the coordinates of a shape/image on the canvas?

Say I drew a rectangle on the canvas. Surely there is some sort of built in method to get the XY coordinates, and dimensions of that rectangle? But after some googling I came up with nothing. And just to clarify, I am not talking about the coordinates of the canvas element itself, but rather a shape/image that is drawn unto the canvas.
Any help is appreciated.
If you're talking about a 2D canvas drawing, then the drawing maps 1:1 with screen coordinates, so it is just location of <canvas> + location of the drawing.
To clarify, drawing on a <canvas> basically just changes the pixels of the canvas - after you draw to it, you can't reference the drawn object the same way you can reference an html element.
Canvas is 2D table (Array) of numbers (= pixels = colors). When drawing into canvas, you are just editing this table. When you draw into canvas (= change numbers in table), what should be the coordinates of your adjustment?
If you are drawing rectangles only and you can define the coordinates for your rectangle, you must know your coordinates inside a program, because you have just drawn it.
If you want your image to be separated into some "objects" (shapes), you should use SVG.
Basically, you should be using canvas as a means to output graphics to the screen and the rest of your logic goes straight into the JavaScript that powers your game/application. The best way to go about making something like this is to create objects and assign properties to them; in its simplest form that can look like this:
function Player(x, y)
{
this.x = x;
this.y = y;
}
var examplePlayerObject = new Player(20, 20);
By extending this object via prototyping you can create multiple copies of an object that has the exact same functions; such as draw. Drawing the player in this instance could just be a red square that is 20px*20px.
Player.prototype.draw = function()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'red';
context.fillRect(this.x, this.y, 20, 20);
}
Then, you should have an update step with some means of clearing what is on the screen and redrawing the parts which have changed.
function animationStep()
{
examplePlayerObject.x++;
examplePlayerObject.y++;
examplePlayerObject.draw();
}
This animation step should run each frame; look into requestAnimationFrame for smooth animation. Paul Irish has a good shim for older browsers. Add in requestAnimationFrame(animationStep) at the end of that function and you will have a red square moving slowly across the screen. Good luck!

Categories