How do I add a shadow to a group of objects, this is not work
var canvas = new fabric.Canvas('container');
var text = new fabric.Text('hello world', {
fontSize: 30
});
//create circle
var circle = new fabric.Circle({
radius: 100,
fill: '#eef',
scaleY: 0.5,
});
var circle2 = new fabric.Circle({
radius: 50,
left: 100,
fill: '#345666',
scaleY: 0.5,
});
//create group
var group = new fabric.Group([circle,circle2], {
angle: -10,
shadow:{ color:"rgb(0,0,0)",blur:20,offsetX:10,offsetY:10 }
});
canvas.add(group);
I know this was a while ago, but it seems shadows on fabric.Group objects is not possible, only on individual objects. Instead why not apply the shadow on the object that forms the background. So in this case it would be:
var newCanvas = new fabric.Canvas('c', {
isDrawingMode: false
});
newCanvas.setWidth(460);
newCanvas.setHeight(365);
var circle = new fabric.Circle({
radius: 100,
fill: '#990000',
originX: 'center',
originY: 'center',
shadow: 'rgba(0,0,0,0.4) 5px 5px 7px'
});
var circle2 = new fabric.Circle({
radius: 50,
fill: '#000000',
originX: 'center',
originY: 'center',
});
var group = new fabric.Group([circle, circle2], {
originX: 'center',
originY: 'center',
left: 225,
top: 185
});
newCanvas.add(group);
newCanvas.renderAll();
* {
box-sizing: border-box;
}
canvas {
border: 1px solid #000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.8/fabric.min.js"></script>
<body>
<div>
<canvas id="c"></canvas>
</div>
</body>
Related
I have 4 lines and a circle. Current the circle can moving to anywhere but I want limit moving for it only on the lines. The example as bellow. I can not found the solution for it.
How can I do that, please help me. Thank you.
var canvas = new fabric.Canvas('canvas');
var line = new fabric.Line([
100, 100, 300, 200
], {
stroke: 'red',
selectable: false
})
var line2 = new fabric.Line([
300, 200, 300, 300
], {
stroke: 'red',
selectable: false
})
var line3 = new fabric.Line([
300, 300, 150, 300
], {
stroke: 'red',
selectable: false
})
var line4 = new fabric.Line([
150, 300, 100, 100
], {
stroke: 'red',
selectable: false
})
var circle = new fabric.Circle({
radius: 10,
fill: '',
stroke: 'red',
strokeWidth: 3,
originX: 'center',
originY: 'center',
top: 100,
left: 100
});
canvas.on('object:moving', function (e) {
})
canvas.add(line);
canvas.add(line2);
canvas.add(line3);
canvas.add(line4);
canvas.add(circle);
canvas.renderAll();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
<canvas id="canvas" width="400" height="400" style="border:1px solid #d3d3d3; position: absolute;">
</canvas>
I'm trying to make a restriction: when a group of objects is selected, some specific object must not be included in the selection.
F.e. we create 3 rectangles. If we select the group and the red one is inside of it, it must be removed from selection:
function addRect(){
var redRect = new fabric.Rect({
left: 50,
top: 50,
fill: 'red',
width: 50,
height: 50
});
var greenRect = new fabric.Rect({
left: 100,
top: 100,
fill: 'green',
width: 50,
height: 50
});
var blueRect = new fabric.Rect({
left: 150,
top: 150,
fill: 'blue',
width: 50,
height: 50
});
canvas.add(redRect);
canvas.add(greenRect);
canvas.add(blueRect);
}
function createCanvas(id){
canvas = new fabric.Canvas(id);
addRect();
canvas.on('selection:created', function(e) {
for (var i = 0; i < canvas.getActiveObjects().length; i++) {
if(canvas.getActiveObjects()[i].fill == "red"){
//somehow remove the red one from selection
};
}
});
return canvas;
}
discardActiveObject() will remove the whole selection.
"selected = false" also doesn't work.
Any ideas?
There are two ways to achieve this using selectable property
http://fabricjs.com/docs/fabric.Rect.html#selectable
By setting selectable: false within the call back function
By setting selectable: false during object creation.
function addRect() {
var redRect = new fabric.Rect({
left: 50,
top: 50,
fill: "red",
width: 50,
height: 50,
selectable: false
});
var greenRect = new fabric.Rect({
left: 100,
top: 100,
fill: "green",
width: 50,
height: 50
});
var blueRect = new fabric.Rect({
left: 150,
top: 150,
fill: "blue",
width: 50,
height: 50
});
canvas.add(redRect);
canvas.add(greenRect);
canvas.add(blueRect);
}
function createCanvas(id) {
canvas = new fabric.Canvas(id, {
height: 500,
width: 800,
backgroundColor: "rgb(100,100,200)",
selectionColor: "blue"
});
addRect();
canvas.on("selection:created", function(e) {
for (var i = 0; i < canvas.getActiveObjects().length; i++) {
if (canvas.getActiveObjects()[i].fill == "red") {
canvas.getActiveObjects()[i].selectable = false;
canvas.renderAll();
}
}
});
return canvas;
}
createCanvas("c");
<script src="https://cdn.jsdelivr.net/npm/fabric#5.2.4-browser/dist/fabric.min.js"></script>
<canvas id="c"> </canvas>
function addRect() {
var redRect = new fabric.Rect({
left: 50,
top: 50,
fill: "red",
width: 50,
height: 50,
selectable: false
});
var greenRect = new fabric.Rect({
left: 100,
top: 100,
fill: "green",
width: 50,
height: 50
});
var blueRect = new fabric.Rect({
left: 150,
top: 150,
fill: "blue",
width: 50,
height: 50
});
canvas.add(redRect);
canvas.add(greenRect);
canvas.add(blueRect);
}
function createCanvas(id) {
canvas = new fabric.Canvas(id, {
height: 500,
width: 800,
backgroundColor: "rgb(100,100,200)",
selectionColor: "blue"
});
addRect();
canvas.on("selection:created", function (e) {
for (var i = 0; i < canvas.getActiveObjects().length; i++) {
if (canvas.getActiveObjects()[i].fill == "red") {
//somehow remove the red one from selection
}
}
});
return canvas;
}
createCanvas("c");
<script src="https://cdn.jsdelivr.net/npm/fabric#5.2.4-browser/dist/fabric.min.js"></script>
<canvas id="c"> </canvas>
I want to make two groups of objects as layers with fabric.js. But although I put the second one with a lower z-index, it is still on top. See the code example below. What is wrong?
var canvas = new fabric.StaticCanvas('canvas');
var render_items = function() {
var rect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 25,
top: 10,
width: 50,
height: 50,
fill: 'red'
});
var layerA = new fabric.Group([rect1], {
originX: 'left',
originY: 'top'
});
canvas.insertAt(layerA, 100);
var rect2 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 30,
top: 20,
width: 50,
height: 50,
fill: 'blue'
});
var layerB = new fabric.Group([rect2], {
originX: 'left',
originY: 'top'
});
canvas.insertAt(layerB, 50);
}();
#canvas {
border:1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="200" height="200"></canvas>
Fabric.JS doesn't really have true z-index functionality as you see with css. Instead, objects on the canvas work like an array where the index of each object determines where it sits in the stacking order. Using canvas.insertAt() lets you specify a specific index to insert the object in the array, and the length of the array is always determined by how many objects there are in your canvas.
Inserting an object at an index of 0 will therefore shift the other objects within the array so that the new object is rendered at the bottom of the stacking order.
var canvas = new fabric.StaticCanvas('canvas');
var render_items = function() {
var rect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 25,
top: 10,
width: 50,
height: 50,
fill: 'red'
});
var layerA = new fabric.Group([rect1], {
originX: 'left',
originY: 'top'
});
canvas.insertAt(layerA, 0);
var rect2 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 30,
top: 20,
width: 50,
height: 50,
fill: 'blue'
});
var layerB = new fabric.Group([rect2], {
originX: 'left',
originY: 'top'
});
canvas.insertAt(layerB, 0);
}();
#canvas {
border:1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="200" height="200"></canvas>
The documentation of Fabric.js on animation mentions this onChange callback:
onChange: canvas.renderAll.bind(canvas)
However, when I try to substitute this with a custom function, the animation does not show. See this example; the down animation does not show, only the up animation. What is wrong with this code?
var canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.set({
hasControls: false,
selectable: false,
hoverCursor: 'default',
originX: 'center',
originY: 'center'
});
rect1 = new fabric.Rect({
left: 200,
top: 0,
width: 50,
height: 50,
fill: 'red',
opacity: 0
});
canvas.add(rect1);
var button01 = new fabric.Circle({
left: 20,
top: 20,
radius: 10,
fill: '#c0c0c0',
strokeWidth: 1,
stroke: '#808080',
hoverCursor: 'pointer'
});
canvas.add(button01);
button01.on('mousedown', function(options) {
animate_down()
});
var text1 = new fabric.Text("Animate", {
fontFamily: 'Arial',
fontSize: 12,
fill: 'black',
left: 58,
top: 20,
});
canvas.add(text1);
function animate_down() {
rect1.animate({
'top': 300,
'opacity': 1
}, {
onChange: function() {
canvas.renderAll.bind(canvas)
/* some other code */
},
onComplete: animate_up,
duration: 2000,
});
}
function animate_up() {
rect1.animate({
'top': 0,
'opacity': 0
}, {
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
});
}
#canvas {
border:1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="300"></canvas>
You need to call canvas.requestRenderAll(); inside your callback. As you are just binding canvas to canvas.renderAll, but never called. Docs
DEMO
var canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.set({
hasControls: false,
selectable: false,
hoverCursor: 'default',
originX: 'center',
originY: 'center'
});
rect1 = new fabric.Rect({
left: 200,
top: 0,
width: 50,
height: 50,
fill: 'red',
opacity: 0
});
canvas.add(rect1);
var button01 = new fabric.Circle({
left: 20,
top: 20,
radius: 10,
fill: '#c0c0c0',
strokeWidth: 1,
stroke: '#808080',
hoverCursor: 'pointer'
});
canvas.add(button01);
button01.on('mousedown', function(options) {
animate_down()
});
var text1 = new fabric.Text("Animate", {
fontFamily: 'Arial',
fontSize: 12,
fill: 'black',
left: 58,
top: 20,
});
canvas.add(text1);
function animate_down() {
rect1.animate({
'top': 300,
'opacity': 1
}, {
onChange: function() {
canvas.requestRenderAll();
/* some other code */
},
onComplete: animate_up,
duration: 2000,
});
}
function animate_up() {
rect1.animate({
'top': 0,
'opacity': 0
}, {
onChange: canvas.requestRenderAll.bind(canvas),
duration: 2000,
});
}
#canvas {
border:1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="300"></canvas>
I want to specify a secondary border color on the selection box.
Example why this is needed. If i have two black rectangle, and select one rectangle, some part of the selection border is not visible above the other rectangle:
var canvas = window.__canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({left: 10, strokeWidth: 0, top: 10, width: 100, height: 100, fill: 'black'});
var rect2 = new fabric.Rect({left: 40, strokeWidth: 0, top: 60, width: 200, height: 200, fill: 'black'});
rect.cornerSize = 8;
rect.padding = 0;
canvas.add(rect);
canvas.add(rect2);
canvas.setActiveObject(rect2);
fabric.Object.prototype.set({
borderColor: 'black',
cornerColor: 'black',
cornerSize: 6,
transparentCorners: true,
borderDashArray: [4, 4],
rotatingPointOffset: 20,
});
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
When an Object is selected set its stroke property to the color you wish. This workaround will serve the purpose.
When an Object is selected, deselected or selection is updated I'm simply setting the stroke and strokeWidth property of an object.
var canvas = window.__canvas = new fabric.Canvas('canvas');
var activeObject;
var lastActiveObject;
canvas.on('selection:created', onObjectSelection);
canvas.on('selection:cleared', onObjectClear);
canvas.on('selection:updated', onselectionUpdate);
function onObjectSelection() {
activeObject = canvas.getActiveObject();
lastActiveObject = activeObject;
activeObject.set({
stroke: 'red',
strokeWidth: 3,
dirty: true
});
canvas.requestRenderAll();
}
function onObjectClear() {
lastActiveObject.set({
stroke: 'black',
strokeWidth: 0,
dirty: true
});
canvas.requestRenderAll();
}
function onselectionUpdate() {
activeObject = canvas.getActiveObject();
activeObject.set({
stroke: 'red',
strokeWidth: 4,
dirty: true
});
lastActiveObject.set({
stroke: 'black',
strokeWidth: 0,
dirty: true
});
canvas.requestRenderAll();
lastActiveObject = activeObject;
}
var rect = new fabric.Rect({
left: 10,
strokeWidth: 0,
top: 10,
width: 100,
height: 100,
fill: 'black'
});
var rect2 = new fabric.Rect({
left: 40,
strokeWidth: 0,
top: 60,
width: 200,
height: 200,
fill: 'black'
});
rect.cornerSize = 8;
rect.padding = 0;
canvas.add(rect);
canvas.add(rect2);
canvas.setActiveObject(rect2);
fabric.Object.prototype.set({
borderColor: 'black',
cornerColor: 'black',
cornerSize: 6,
transparentCorners: true,
borderDashArray: [4, 4],
rotatingPointOffset: 20,
});
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>