How to select only the stroke in a transparent backgroud rectangle? - javascript

How can i make a transparent rectangle selectable only when i click on the stroke? I tried two different approach as you can see from the snippet below, the object on the left is a rectangle with a transparent background, the object on the right is a group object with multiple lines. I want to know how to be able to select the element only when i click on the stroke, with both objects if you click on the inner transparent area the object becomes selected.
var canvas = new fabric.Canvas('a');
canvas.add(new fabric.Rect({
left: 10,
top: 20,
height: 160,
width: 80,
fill: 'transparent',
stroke: 'red'
}));
var rectLine1 = new fabric.Line([0, 0, 80, 0], {
stroke: 'red',
left: 100,
top: 20
});
var rectLine2 = new fabric.Line([0, 160, 0, 0], {
stroke: 'red',
left: 100,
top: 20
});
var rectLine3 = new fabric.Line([0, 160, 0, 0], {
stroke: 'red',
left: 180,
top: 20
});
let rectLine4 = new fabric.Line([0, 0, 80, 0], {
stroke: 'red',
left: 100,
top: 180
});
var group = new fabric.Group([rectLine1, rectLine2, rectLine3, rectLine4], {
left: 110,
top: 20
})
canvas.add(group)
canvas.renderAll();
.c {
border: 2px solid black;
}
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<canvas id="a" class="c" width="200" height="200"></canvas>

I found that setting perPixelTargetFind: true solves the problem, you can also set a tolerance on the canvas targetFindTolerance: 10 to be able to select objects with thin strokes. I'll paste the working code below in case anyone needs it.
var canvas = new fabric.Canvas('a', {
targetFindTolerance: 10
});
canvas.add(new fabric.Rect({
left: 10,
top: 20,
height: 160,
width: 80,
fill: 'transparent',
stroke: 'red',
perPixelTargetFind: true,
}));
canvas.renderAll();
.c {
border: 2px solid black;
}
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<canvas id="a" class="c" width="200" height="200"></canvas>

Related

how to hide the handle that changes the aspect ratio in fabric.js

I don't want to change the aspect ratio of the object, so I want to hide the handles other than the four corners.
In the following page, if you select "select rectangle", handles will be displayed in between the four corners, and if you operate it, the aspect ratio will change.
https://codepen.io/janih/pen/zGxoZv
handle image
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- http://stackoverflow.com/questions/20096949/how-to-select-fabric-js-object-programmatically -->
<!-- http://jsfiddle.net/ThzXM/1/ -->
<style>
canvas {
border: 1px solid #ccc;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
var canvas = new fabric.Canvas('canvas');
canvas.add(new fabric.Rect({
left: 100,
top: 100,
width: 75,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 3,
padding: 10
}));
canvas.add(new fabric.Circle({
left: 200,
top: 200,
radius: 30,
fill: 'gray',
stroke: 'black',
strokeWidth: 3
}));
$( "#selectrectangle" ).click(function() {
canvas.setActiveObject(canvas.item(0));
});
$( "#selectsecond" ).click(function() {
canvas.setActiveObject(canvas.item(1));
});
canvas.renderAll();
});
</script>
</head>
<body>
<input id = "selectrectangle" type="button" value="select rectangle"/>
<input id = "selectsecond" type="button" value="select second object"/>
<canvas id="canvas" width="400" height="400" style="border:1px solid red"/>
</body
</html>
version
fabric.js v4.6.0
You use the setControlsVisibility method on a fabric object:
obj.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false
});
Documentation is here: http://fabricjs.com/controls-customization
Fiddle: http://jsfiddle.net/av01d/pnrvmc93/

selection border is incorrect while canvas's zoom value is not 1

Version 2.3.6
Steps to reproduce:
click 'select-all', selection is all right.
next click 'set zoom as 1.5' ,
then click 'select-all',
Result: Selection border is incorrect now.
$(document).ready(function() {
var canvas = new fabric.Canvas('canvas');
canvas.add(new fabric.Rect({
left: 50,
top: 50,
width: 75,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 3,
padding: 10
}));
canvas.add(new fabric.Circle({
left: 120,
top: 120,
radius: 30,
fill: 'gray',
stroke: 'black',
strokeWidth: 3
}));
$("#select-all").click(function() {
canvas.discardActiveObject();
var elements = canvas.getObjects();
var selection = new fabric.ActiveSelection(elements);
canvas.setActiveObject(selection);
canvas.requestRenderAll();
});
$("#set-zoom-15").click(function() {
canvas.setZoom(1.2);
});
$("#set-zoom-10").click(function() {
canvas.setZoom(1.0);
});
canvas.renderAll();
});
canvas {
border: 1px solid #ccc;
margin-top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<input id="select-all" type="button" value="select all" />
<input id="set-zoom-15" type="button" value="set zoom as 1.5" />
<input id="set-zoom-10" type="button" value="set zoom as 1" />
<canvas id="canvas" width="400" height="400" style="border:1px solid red" />
Expected Behavior:
Selection works fine ( like zoom is 1 ) when the zoom is 1.5.
Actual Behavior:
Selection is incorrect when the zoom is 1.5.
When you create your ActiveSelection, you need to pass in the canvas object.
var selection = new fabric.ActiveSelection(elements, {
canvas: canvas,
});
See http://fabricjs.com/manage-selection for documentation.
$(document).ready(function() {
var canvas = new fabric.Canvas('canvas');
canvas.add(new fabric.Rect({
left: 50,
top: 50,
width: 75,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 3,
padding: 10
}));
canvas.add(new fabric.Circle({
left: 120,
top: 120,
radius: 30,
fill: 'gray',
stroke: 'black',
strokeWidth: 3
}));
$("#select-all").click(function() {
canvas.discardActiveObject();
var elements = canvas.getObjects();
var selection = new fabric.ActiveSelection(elements, {
canvas: canvas,
});
canvas.setActiveObject(selection);
canvas.requestRenderAll();
});
$("#set-zoom-15").click(function() {
canvas.setZoom(1.2);
});
$("#set-zoom-10").click(function() {
canvas.setZoom(1.0);
});
canvas.renderAll();
});
canvas {
border: 1px solid #ccc;
margin-top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<input id="select-all" type="button" value="select all" />
<input id="set-zoom-15" type="button" value="set zoom as 1.5" />
<input id="set-zoom-10" type="button" value="set zoom as 1" />
<canvas id="canvas" width="400" height="400" style="border:1px solid red" />

How to style part of my drawn fabricjs text object?

I have some code that allows me to toggle between text objects. I'd like to have the text objects include some styling, like Bold, Italic, etc for titles and such. text, however, am not sure how to accomplish this. Here's my current code:
var canvas = this.__canvas = new fabric.Canvas('c');
canvas.setHeight(300);
canvas.setWidth(500);
function textOne() {
canvas.clear();
canvas.add(new fabric.IText('Regular Font', {
left: 50,
top: 100,
fontFamily: 'arial',
fill: '#333',
fontSize: 50
}));
}
function textTwo() {
canvas.clear();
canvas.add(new fabric.IText('Bold Font', {
left: 50,
top: 100,
fontFamily: 'arial',
fontWeight: 'bold',
fill: '#333',
fontSize: 50
}));
}
canvas {
border: 1px solid #dddddd;
border-radius: 3px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<button onclick="textOne()">One</button>
<button onclick="textTwo()">Two</button>
<canvas id="c"></canvas>
You can use the styles property to style individual characters
http://fabricjs.com/docs/fabric.IText.html#styles
var canvas = this.__canvas = new fabric.Canvas('c');
canvas.setHeight(300);
canvas.setWidth(500);
function textOne() {
canvas.clear();
canvas.add(new fabric.IText('Regular Font', {
left: 50,
top: 100,
fontFamily: 'arial',
fill: '#333',
fontSize: 50,
styles:{
0:{
0:{fontWeight: 'bold'},
1:{fontWeight: 'bold'}
}
}
}));
}
function textTwo() {
canvas.clear();
canvas.add(new fabric.IText('Bold Font', {
left: 50,
top: 100,
fontFamily: 'arial',
fontWeight: 'bold',
fill: '#333',
fontSize: 50,
styles:{
0:{
0:{fontSize: 40},
1:{fontSize: 30}
}
}
}));
}
canvas {
border: 1px solid #dddddd;
border-radius: 3px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<button onclick="textOne()">One</button>
<button onclick="textTwo()">Two</button>
<canvas id="c"></canvas>
If you want to also update the styles dynamically, you can use setSelectionStyles method like this:
const text = new fabric.TextBox('Regular Font', {
left: 50,
top: 100,
fontFamily: 'arial',
fill: '#333',
fontSize: 50,
});
const start = 0
const end = 5
text.setSelectionStyles({fontWeight: 'bold'}, start, end);

How to display element in proper position in FabricJs despite on it originX and Y?

I have two almost identical elements except for their top and origin.
I don't understand how to place them on the same left with 2 different origins.
Here is the expected view:
And here is what I get:
--> Here is the link to jsFiddler <--
Note: Their LEFT is same! This is what I'm getting from backend.
Tnx
var canvas = new fabric.Canvas('paper');
const red = new fabric.Rect({
left: 100,
top: 50,
fill: 'red',
width: 200,
height: 100,
originX: 'center',
originY: 'center'
});
const yellow = new fabric.Rect({
left: 100,
top: 150,
fill: 'yellow',
width: 200,
height: 100,
originX: 'left',
originY: 'top'
});
canvas.add(red);
canvas.add(yellow);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.0/fabric.min.js"></script>
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>
Is this what you want? Here left and top attrs are same.
var canvas = new fabric.Canvas('paper');
const red = new fabric.Rect({
left: 100,
top: 150,
fill: 'red',
width: 200,
height: 100,
originX: 'left',
originY: 'bottom'
});
const yellow = new fabric.Rect({
left: 100,
top: 150,
fill: 'yellow',
width: 200,
height: 100,
originX: 'left',
originY: 'top'
});
canvas.add(red);
canvas.add(yellow);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.0/fabric.min.js"></script>
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>

FabricJS iText grow from center

How can you make a text object on the FabricJS canvas grow/shrink from the center and expand bidirectionally when text is added or removed?
I have tried adding centeredScaling: true but this is only for resizing (scaling) the object, not adding/removing text.
If you check my demo you'll see that when you click the text and add more characters to the object it expands to the right only, leaving the text off center.
var canvas = this.__canvas = new fabric.Canvas('c');
var cWidth = 600;
var cHeight = 200;
canvas.setWidth(cWidth);
canvas.setHeight(cHeight);
function Addtext() {
canvas.add(new fabric.IText('Text', {
left: (cWidth / 2) - 83,
top: (cHeight / 2) - 25,
fontFamily: 'arial black',
fill: '#333',
fontSize: 50,
centeredScaling: true,
}));
}
#c {
border: 1px solid red;
top: 22px;
left: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<button onclick="Addtext()">Add Text</button>
<canvas id="c"></canvas>
Add align and origin of x and y to center.
var canvas = this.__canvas = new fabric.Canvas('c');
var cWidth = 600;
var cHeight = 200;
canvas.setWidth(cWidth);
canvas.setHeight(cHeight);
function Addtext() {
canvas.add(new fabric.IText('Text', {
left: (cWidth / 2) - 83,
top: (cHeight / 2) - 25,
fontFamily: 'arial black',
fill: '#333',
fontSize: 50,
align: 'mid', //added
originX: 'center', //added
originY: 'center', //added
centeredScaling: true,
}));
}
#c {
border: 1px solid red;
top: 22px;
left: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<button onclick="Addtext()">Add Text</button>
<canvas id="c"></canvas>

Categories