How can I disable object selection outside of clipPath?
var canvas = new fabric.Canvas('c');
var clipath = new fabric.Rect({ width: 400, height: 300,left:50,fill: '#eee', absolutePositioned: true, selectable: false,hoverCursor: "default",strokeWidth: 0 });
var rect = new fabric.Rect({ width: 100, height: 100, fill: 'red',left:80,top:20 });
rect.clipPath = clipath;
canvas.add(clipath);
canvas.add(rect);
<canvas id="c" width="600" height="350" style="border:1px solid #ccc"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
Related
Recently I have started to use a newer version of Fabric.js (from 1.7.22 to 2.3.5). I had to make a few modifications to existing code that seem logical to me. However, I notice that you cannot initially place an object outside the canvas anymore, to reposition it later onto the canvas. Like in the code below. It won't show. My question is: has this changed for some reason, or is this an issue (bug)? And do I have other options than postpone adding the object to the canvas, or using the visible attribute?
$( document ).ready(() => {
const canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 301,
top: 10,
originX: 'left',
originY: 'top',
width: 50,
height: 50,
fill: '#336699'
});
canvas.add(rect);
rect.set({"left": 10});
rect.set({"top": 10});
canvas.renderAll();
});
canvas {
border: 1px solid tomato;
}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="100"></canvas>
You need to use setCoords() after repositioning.
$( document ).ready(() => {
const canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 301,
top: 10,
originX: 'left',
originY: 'top',
width: 50,
height: 50,
fill: '#336699'
});
canvas.add(rect);
rect.set({"left": 10});
rect.set({"top": 10});
rect.setCoords();
canvas.renderAll();
});
canvas {
border: 1px solid tomato;
}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="100"></canvas>
var canvas = new fabric.Canvas('c');
canvas.add(new fabric.Rect({
left:10,
top:10,
width:50,
height:50,
fill:'#4169e1'
}));
canvas.add(new fabric.Rect({
left:140,
top:140,
width:50,
height:50,
fill:'#800000'
}));
canvas {
border: black solid 1px;
padding: 5px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.min.js"></script>
<input type='color'></input>
<canvas id="c" width="200" height="200"></canvas>
I want to be able to select an object and the input field updates with the color, AND be able to change the color of the object from the input field. I know I can do one way binding with document.getElementById("example").innerHTML and '<input type="color" value="' + canvas.getActiveObject().fill +'">', but what is the best way for two way binding?
You need to use events object:selected selection:cleared to get the selected object. And set the color picker value from selected object fill value.
DEMO
var canvas = new fabric.Canvas('c');
canvas.add(new fabric.Rect({
left: 10,
top: 10,
width: 50,
height: 50,
fill: '#4169e1'
}));
canvas.add(new fabric.Rect({
left: 140,
top: 140,
width: 50,
height: 50,
fill: '#800000'
}));
var colorPick = document.getElementById('colorPick');
var activeSelected;
colorPick.onchange = function() {
if (activeSelected) {
activeSelected.fill = this.value;
activeSelected.dirty = true;
canvas.renderAll();
}
};
canvas.on('object:selected', function(option) {
activeSelected = option.target;
colorPick.value = activeSelected.fill;
})
canvas.on('selection:cleared', function(option) {
activeSelected = null;
console.log(activeSelected)
});
canvas {
border: black solid 1px;
padding: 5px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.min.js"></script>
<input type='color' id='colorPick'></input>
<canvas id="c" width="200" height="200"></canvas>
I've a problem with my FabricJS app. By default, the object layer in fabricjs jumps to the top when I select it.
I want to disable this option so that the index of the active element not changing. It's possible ?
You just need to set the preserveObjectStacking options as shown in the below code when setting up the canvas.
var fabricCanvas = new fabric.Canvas("t", { preserveObjectStacking: true });
fabricCanvas
.add(new fabric.Rect({
top: 0,
left: 0,
width: 100,
height: 100,
fill: "green"
}))
.add(new fabric.Rect({
top: 50,
left: 50,
width: 100,
height: 100,
fill: "red"
}))
.add(new fabric.Rect({
top: 100,
left: 100,
width: 100,
height: 100,
fill: "blue"
}))
.renderAll();
canvas {
border: 1px solid black;
}
<canvas id="t" width="400" height="300"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script>
In native HTML5 canvas the text is positioned by the text baseline but in Fabric.js it seems to be by the bottom of the text. I want Fabric.js to position text by the baseline. Is it possible?
See image
This is the code used for the example.
Fabric.js<br />
<canvas id="fabric" width="300" height="300" style="border:1px solid #d3d3d3;"></canvas>
<script src="fabric.js"></script>
<script>
var canvas = new fabric.Canvas('fabric');
canvas.add(new fabric.Line([100, 100, 200, 100], { left: 10, top: 50, stroke: 'red' }));
canvas.add(new fabric.Text('Hello World', { left: 10, top: 50, originY: 'bottom', useNative: true, fontSize: 50 }));
</script>
<br />
Native HTML5<br />
<canvas id="native" width="300" height="300" style="border:1px solid #d3d3d3;"></canvas>
<script>
var c = document.getElementById("native");
var ctx = c.getContext("2d");
ctx.font = "50px Times New Roman";
ctx.fillText("Hello World",10,50);
ctx.moveTo(10,50);
ctx.lineTo(100,50);
ctx.strokeStyle = '#ff0000';
ctx.stroke();
</script>
Unfortunately, it doesn't look possible at the moment. The textBaseline attribute is set to 'alphabetic' and the only available vertical alignment options are 'top', 'center', & 'bottom' (which are relative to the bounding box fabric draws around the text).
I've created an issue to request this feature. Hopefully, they add it!
I am creating SVG shape and exporting it to database. The jsfiddle for this is here - http://jsfiddle.net/rafi_ccj/MASeK/1/
And the code is below.
HTML part:
<button id="make_svg">toSVG</button>
<div id="canvas-wrapper">
<canvas id="canvas" width="400px" height="200px"></canvas>
</div>
Javascript part:
var canvas = new fabric.Canvas('canvas');
canvas.add(new fabric.Rect({
left: 100,
top: 100,
angle: 0,
fill: 'rgba(23,23,125,0.5)',
strokeWidth: 0.1,
stroke: '#FF0000',
width: 200,
height: 200,
opacity: 1
}));
canvas.add(new fabric.Circle({
left: 100,
top: 100,
fill: 'rgba(45, 255, 34, 0.5)',
strokeWidth: 0.1,
stroke: '#FF0000',
radius: 100,
opacity: 1
}));
$("#make_svg").click(function () {
canvas_data = canvas.toSVG();
console.log(canvas_data);
});
and then i am importing that svg into canvas but it is not same i did create. the jsfiddle is here - http://jsfiddle.net/rafi_ccj/2vtz2/
and the code is below---
html part
<div id="canvas-wrapper">
<canvas id="canvas" width="900px" height="800px"></canvas>
</div>
javascript part is here -
var canvas = new fabric.Canvas('canvas');
var canvas_data = '<?xml version="1.0" standalone="no" ?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="200" xml:space="preserve"><desc>Created with Fabric.js 1.1.8</desc><defs></defs><rect x="-100" y="-100" rx="0" ry="0" width="200" height="200" style="stroke: #FF0000; stroke-width: 0.1; stroke-dasharray: ; fill: rgba(23,23,125,0.5); opacity: 1;" transform="translate(100 100)"/><circle cx="0" cy="0" r="100" style="stroke: #FF0000; stroke-width: 0.1; stroke-dasharray: ; fill: rgba(45, 255, 34, 0.5); opacity: 1;" transform="translate(100 100)"/></svg> ';
fabric.loadSVGFromString(canvas_data, function (objects, options) {
var loadedObject = fabric.util.groupSVGElements(objects, options);
loadedObject.set({
left: 400,
top: 200
});
loadedObject.setCoords();
canvas.add(loadedObject);
canvas.calcOffset();
});
i also have noticed that if i use triangle, it is not present after import, it is just vanished.
can anyone please help me in this problem?
I have solved this problem by making all objects a group element, and after creating the group with these objects existed in the canvas, i have saved it with svg extension in device and also a json format in the database. Code is below-
var group = new fabric.Group([],{
left: 200,
top: 200
});
var canvas_item = canvas.item(0), x = 0;
while (canvas_item != undefined) {
group.addWithUpdate(canvas_item);
x += 1;
canvas_item = canvas.item(x);
}
canvas.clear();
canvas.add(group);
//then use canvas.toDatalessJSON(); and save it to database. while importing this data //use following codes
var canvas_data = JSON.stringify(canvas.toDatalessJSON());
canvasJSONdata = JSON.stringify(canvas.toDatalessJSON());
var stringifiedCanvasJSONdata = JSON.parse(canvasJSONdata,'');
var base_64 = canvas.toDataURL('png');
and now it is working perfect! Though i have faced many problems, i have learned a lot, i have enjoyed it! Hope this solution will help someone someday.