On mouse click event, a rectangle is added to the canvas:
canvas.on({
'mouse:down': function(options) {
canvas.add(new fabric.Rect({
left: options.e.clientX,
top: options.e.clientY,
fill: 'red',
width: 20,
height: 20
}));
}
});
If I click somewhere else a second rectangle is drawn, and so on. I want the previous rectangle to be removed, for every new mouse click event.
I can't use animate() in this case, cause in my application there will be a lot of rectangles drawn and I need to just redraw new rectangles on new places, not moving every one of them.
In native canvas I could just use clearRect() to clear the whole canvas and redraw a new rectangle in the new place. How can I do something like that when using Fabric.js?
You could create only one rectangle object, and change its left and top position for subsequent mouse down events.
DEMO
var canvas = new fabric.Canvas('canvas',{selection:false});
var rect = new fabric.Rect({
fill: 'red',
width: 20,
height: 20,
visible:false
});
canvas.add(rect);
canvas.on('mouse:down', function(options) {
var pointer = canvas.getPointer(options.e);
rect.set({
left: pointer.x,
top: pointer.y,
visible:true
});
canvas.renderAll();
});
canvas{
border:2px solid #000;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id='canvas' width=500 height=400>
Related
I need to change the cursor types as "Handwriting" on hover shapes...
var canvas = window._canvas = new fabric.Canvas('ImgCanvas');
function changeCursor(cursorType) {
canvas.defaultCursor = "Handwriting";
}
I tried this but not working
You can change the hoverCursor directly to the single shape, or globally to the entire canvas. Take a look to the snippet below.
var canvas = this.__canvas = new fabric.Canvas('c');
// pointer for all
canvas.hoverCursor = 'pointer';
var rect = new fabric.Rect({
left: 50,
top: 30,
width: 100,
height: 100,
fill: 'green',
angle: 20,
});
var rect2 = new fabric.Rect({
left: 180,
top: 30,
width: 100,
height: 100,
fill: 'green',
angle: 20,
});
canvas.add(rect);
canvas.add(rect2);
canvas.renderAll();
var canvas2 = this.__canvas = new fabric.Canvas('c2');
var rect = new fabric.Rect({
left: 120,
top: 30,
width: 100,
height: 100,
fill: 'green',
angle: 20,
// pointer for the selected shape
hoverCursor: "pointer"
});
canvas2.add(rect);
canvas2.renderAll();
p{font-family:'arial'}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<p>Applied Globally</p>
<canvas height=200 width=300 id="c" style="border:1px solid black"></canvas>
<p>Applied individually</p>
<hr/>
<canvas height=200 width=300 id="c2" style="border:1px solid black"></canvas>
Surendhar,
To change cursor over the shape you need to defined as:
canvas.hoverCursor = 'cursor type'
This is a list of cursors
If you need custom cursor you have to create div element on top the fabric canvas with custom cursor. When you have event 'mouseover' the shape just specified canvas.hoverCursor = 'none', and show custom one.
You can check this fiddle it is simple example of custom cursor. You have to revisit this code in order to work without refreshing of custom cursor. It is all about mouse-over events of custom cursor. You have to disable mouse-over event of each div element of custom cursor.
For fabric 4.6, besides the default cursors, also be able to set custom cursor with png:
const canvas = new fabric.Canvas('c');
const cursorUrl = 'https://ossrs.net/wiki/images/figma-cursor.png';
canvas.defaultCursor = `url(" ${cursorUrl} "), auto`;
canvas.hoverCursor = `url(" ${cursorUrl} "), auto`;
canvas.moveCursor = `url(" ${cursorUrl} "), auto`;
CodePen
Here's a simple way to customize the cursor and create a hand grab effect when moving an object.
this.canvas = new fabric.Canvas('canvas', {
defaultCursor:'default',
hoverCursor: 'grab',
moveCursor:'grabbing',
selection: true,
backgroundColor: '#ffffff',
});
Here you find the list of all cursors
https://www.w3schools.com/cssref/playit.asp?filename=playcss_cursor&preval=alias
To change the cursor of a fabric.js object, you can set the hoverCursor or moveCursor to your own image.
E.g:
object.set({hoverCursor: 'url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/9632/happy.png"), auto'});
After rotating object is it possible to get left,top and right position of virtual rectangle?
What you are looking for is the bounding rect of your object:
getBoundingRect(ignoreVpt) → {Object} Returns coordinates of object's
bounding rectangle (left, top, width, height) the box is intented as
aligned to axis of canvas.
Returns: Object with left, top, width, height properties Type Object
reference: fabricjs sourcecode
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
var rect = new fabric.Rect({
left: 120,
top: 30,
width: 100,
height: 100,
fill: 'green',
angle: 20
});
canvas.on('after:render', function() {
canvas.contextContainer.strokeStyle = '#555';
canvas.forEachObject(function(obj) {
var bound = obj.getBoundingRect(); // <== this is the magic
console.log(bound);
canvas.contextContainer.strokeRect(
bound.left,
bound.top,
bound.width,
bound.height
);
});
});
canvas.add(rect);
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas height=200 width=300 id="c" style="border:1px solid black"></canvas>
Since the after:render event is fired continuously after each frame is rendered you can see the updated bounding box of your object for every update, in position, rotation and dimensions.
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
var rect = new fabric.Rect({
left: 120,
top: 30,
width: 100,
height: 100,
fill: 'green',
angle: 20
});
canvas.add(rect);
canvas.on('after:render', function() {
canvas.contextContainer.strokeStyle = '#555';
var ao = canvas.getActiveObject();
if (ao) {
var bound = ao.getBoundingRect();
canvas.contextContainer.strokeRect(
bound.left,
bound.top,
bound.width,
bound.height
);
console.log(bound);
}
});
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas height=200 width=300 id="c" style="border:1px solid black"></canvas>
For reference Working with events
I am working on a fabricjs application & i need to set a inside stroke to object, it means apply stroke to a object without increase it's size.
eg if i apply strokeWidth 20 to 100*100 rect then it's size is also increase but i want if stroke is apply to object then size will also remain same
var recta = new fabric.Rect({
left: 10,
top: 10,
fill: '#000',
width: 100,
height: 100,
});
var rectb = new fabric.Rect({
left: 150,
top: 10,
fill: '#000',
width: 100,
height: 100,
});
canvas.add(recta, rectb);
rectb.set('stroke', '#f00');
rectb.set('strokeWidth', 20);
canvas.renderAll();
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas style="border:#000 1px solid" id="design-canvas" width="500" height="400">
<script type="text/javascript">
canvas = new fabric.Canvas('design-canvas');
</script>
Is there is any way or trick to apply stroke without increase size
Thanks in Advance
Assuming it'd just be for rectangles, The best way would likely be too attach 4 lines which you update the positions based off of that rectangles x, y, width and height. You can then set the stroked width of those lines separately.
The other way would be too simply resize the owning element. Look at this JSFiddle.
var canvas = new fabric.Canvas('c', { selection: false });
var circle, isDown, origX, origY;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: pointer.x,
top: pointer.y,
radius: 1,
strokeWidth: 5,
stroke: 'red',
selectable: false,
originX: 'center', originY: 'center'
});
canvas.add(circle);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
circle.set({ radius: Math.abs(origX - pointer.x) });
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
I created a canvas and I can add objects. How can I remove the item clicked?
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: 'green',
width: 40,
height: 80
});
var circle = new fabric.Circle({
radius: 20,
fill: 'red',
left: 100,
top: 100
});
canvas.add(rect);
canvas.add(circle);
Fabric.js provides object:selected event on canvas. You can listen to this event and then remove the item it occurred on. Here's the sample code:
canvas.on('object:selected',function(ev){
canvas.remove(ev.target);
});
You can read the documentation and look at the jsfiddle i created here: http://jsfiddle.net/yrL4eLsn/1/
Please refer fabrics readme : fabricjs.com/fabric-intro-part-2/
canvas.on('mouse:down', function(options) {if (options.target){console.log('an object was clicked!',options.target.type);canvas.remove(options.target);}});
Posting code in single line as I am using a cellphone
I have started using fabric.js today for drawing on my canvas using different modes. That means when I click lines button I shall be able to draw straight lines on canvas. When I press rectangles button I shall be able to draw rectangles and same with freehand button. I am able to draw all of them.
Problem comes here. Once I draw any shape and try to draw some thing else near the old shape, the previous shape is becoming movable.
Here is my code
<%# taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<style>
#myCanvas { background:url("images/<s:property value="userImageFileName"/>") ;
background-size: 100% 100%;
background-repeat: no-repeat;}
</style>
<script type="text/javascript" src="fabric.js"></script>
<script type="text/javascript" src="jscolor.js"></script>
</head>
<body>
<img id="result" src="images/<s:property value="userImageFileName"/>" hidden="true" width="565" height="584" class="annotatable"/>
<canvas id="myCanvas" width="565" height="584" style="border:1px solid #d3d3d3;">Please use a modern browser like Firefox, Chrome, Safari</canvas>
<div >Choose Color</div>
<input class="color" id="selectedColor">
<input type="button" value="rectangles" onClick="operate('rectangles')">
<input type="button" value="freehand" onClick="operate('freehand')">
<input type="button" value="lines" onClick="operate('lines')">
<input type="submit" value="save" onClick="save()">
<br>
<canvas id="canvas2" width="565" height="584"></canvas>
<img id="canvasImg" alt="No annotated image found">
<script>
var canvas = new fabric.Canvas('myCanvas', { selection: false });
var drawRectangle = false;
var color;
function operate(mode)
{
var line, mouseClicked = false;
canvas.on('mouse:down', function(o)
{
mouseClicked = true;
var pointer = canvas.getPointer(o.e);
color=document.getElementById("selectedColor").value;
if(mode=="freehand")
{
canvas.isDrawingMode = true;
drawRectangle = false;
canvas.freeDrawingBrush.width = 5;
canvas.freeDrawingBrush.color = '#'+color;
}
else if(mode=="lines")
{
canvas.isDrawingMode = false;
drawRectangle = false;
var points = [ pointer.x, pointer.y, pointer.x, pointer.y ];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
canvas.add(line);
}
else if(mode=="rectangles")
{
canvas.isDrawingMode = false;
drawRectangle = true;
origX = pointer.x;
origY = pointer.y;
var pointer = canvas.getPointer(o.e);
rect = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x-origX,
height: pointer.y-origY,
angle: 0,
transparentCorners: false,
stroke: "red",
fill:"transparent",
strokeWidth: 5
});
canvas.add(rect);
}
});
canvas.on('mouse:move', function(o)
{
if (!mouseClicked) return;
var pointer = canvas.getPointer(o.e);
if(mode=="lines")
{
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
}
else if(mode=="rectangles")
{
if(origX>pointer.x){
rect.set({ left: Math.abs(pointer.x) });
}
if(origY>pointer.y){
rect.set({ top: Math.abs(pointer.y) });
}
rect.set({ width: Math.abs(origX - pointer.x) });
rect.set({ height: Math.abs(origY - pointer.y) });
canvas.renderAll();
}
});
canvas.on('mouse:up', function(o){
mouseClicked = false;
});
}
function save(){
var canvas2 = document.getElementById('canvas2');
var context2 = canvas2.getContext('2d');
var img=document.getElementById("result");
context2.drawImage(img, 0, 0, 565, 584);
context2.drawImage(canvas, 0, 0);
var canvasData = canvas2.toDataURL();
//document.write(dataURL);
document.getElementById('canvasImg').src = canvasData;
};
</script>
</body>
</html>
Also I am getting problem with saving the canvas as image. The saving code in the given code is my old code which was working fine before I switched to fabric.js.
In the image You can see the outline of the shape which is allowing me to move that shape.,but I don't want that. How can I get rid of it.
Hmm, it may seem a tad expensive, but consider setting all other objects on the canvas to have their selectable or evented property set to false. Doing so will ensure that none that they won't react to any mouse input while you're drawing.
selectable controls if the object can be physically selected, while evented prevents it from reacting with any events whatsoever.
As far as your save() function, it looks as if you are accessing the toDataURL() method of the regular HTML5 Canvas API. That may seem to work, but remember that fabric uses two canvas elements behind-the-scenes. You likely wouldn't be getting the full image. use the toDataURL method of your fabric.Canvas instance that you declared at the top of your code, and that should be all you need. You won't need to find the context of the canvas or anything like that either.