Why do i have a horizontal gray line in the middle of two rects ? Even when i set hasBorder to false!
fabric.Rect.prototype.backgroundColor = '#000'
fabric.Rect.prototype.opacity = 0.7
fabric.Rect.prototype.selectable = false
fabric.Rect.prototype.hasBorder = false
var canvas = new fabric.Canvas('c')
var rect1 = new fabric.Rect({
left: 0,
top: 0,
width: 500,
height: 100
})
var rect2 = new fabric.Rect({
left: 0,
top: 100,
width: 500,
height: 100
})
canvas.add(rect1, rect2)
see fiddle here
Any answer will be appreciated, thanks!
It is hasBorders (instead of hasBorder)
Fiddle - http://jsfiddle.net/m7djt7ty/
I finally find the answer to the gray line appearing is because the rect's height is decimals, maybe my math calc should be more precise! Or to use another way to calc with decimals.
Thanks again!
Related
I am using fabric.js for canvas shapes. but now i have to add border with outline on these shapes like below. How it is possible in fabricjs??. Or do we have any other js library to get same output?
I want below output:
Why not create a group out of two rectangles? Like so:
var canvas = this.__canvas = new fabric.StaticCanvas('c');
var rectBack = new fabric.Rect({
width: 170,
height: 170,
top: 0,
left: 0,
fill: 'rgba(0,0,255,1.0)',
rx: 2,
ry: 2
});
var outerMargin = 10
var innerOutlineWidth = 4
var innerOutline = new fabric.Rect({
width: 170 - outerMargin - innerOutlineWidth/2,
height: 170 - outerMargin - innerOutlineWidth/2,
top: outerMargin/2,
left: outerMargin/2,
stroke: 'rgba(255,255,255,1.0)',
fill: 'rgba(0,0,0,0.0)',
strokeWidth: innerOutlineWidth,
rx: 10,
ry: 10
});
var group = new fabric.Group([rectBack, innerOutline], {
left: 0,
top: 0,
angle: 0
});
canvas.add(group);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js"></script>
<canvas id="c" width="200" height="200"></canvas>
Any framework you use is going to have some fundamental building blocks you have to piece together to get what you want. So I would not recommend jumping to another one.
I have two canvas objects (Rectungle and Triangle) in group.
Then i need to delete them, then return one of objects to is past position.
Here is two objects and group
var rect1 = new fabric.Rect(
{
id: 1, left: 10, top: 10, width: 100, height: 50, angle: 45, fill: 'red'
});
var tria1 = new fabric.Triangle({
id: 2, left: 200, top: 200, width: 100, height: 50, angle: 20, fill: 'yellow'
});
var objsGroup = new fabric.Group([rect1, tria1], {left: 100, top: 100});
And the whole fiddle here. I separate all steps by alerts https://jsfiddle.net/5js60oec/
UPDATE
Have the next problem. Lets assume that existing object group making some move and rotating before deleting. Then i have to restore it to point before rotating and moving. Thats, i think the main problem.
Actions
objsGroup.top = 200;
objsGroup.left = 200;
canvas.renderAll();
alert('4');
history.push(canvas.getActiveGroup());
objsGroup.setAngle(45);
canvas.renderAll();
Here the full fiddler: https://jsfiddle.net/nppaLetn/1/
For example I am deleting the last added path in my canvas like below
var lastItemIndex = (fabricCanvas.getObjects().length - 1);
var item = fabricCanvas.item(lastItemIndex);
if(item.get('type') === 'path') {
fabricCanvas.remove(item);
fabricCanvas.renderAll();
}
This may help you to accomplish your probs!!! I think so .
I just want to know what is the best way to use multiple canvas in a single page. These canvas can be overlapped on each other.
I tried to search this issue on different form, but wasn't able to find any helpful material. This is what we actually want to do(in the following image). There are 5 canvases, and we want all of them to be fully functional. We can add images, text and draw different things on selected canvas.
We are currently using fabricjs.
If that`s not possible, what is the best solution for achieving something like that ?
Thanks in advance!
Simply use CSS for that.
<div class="wrapper">
<canvas id="background_layer" class="canvas-layer" width="100" height="100"></canvas>
<canvas id="other_layer" class="canvas-layer" width="100" height="100"></canvas>
</div>
<style>
.wrapper { position: relative }
.canvas-layer {
position: absolute; left: 0; top: 0;
}
</style>
I am not sure what you are trying to achieve but you can refer to this Fiddle http://jsfiddle.net/PromInc/ZxYCP/
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var canvas = new fabric.Canvas('c');
// Note the use of the `originX` and `originY` properties, which we set
// to 'left' and 'top', respectively. This makes the math in the `clipTo`
// functions a little bit more straight-forward.
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 180,
top: 10,
width: 200,
height: 200,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 0,
selectable: false
});
// We give these `Rect` objects a name property so the `clipTo` functions can
// find the one by which they want to be clipped.
clipRect1.set({
clipFor: 'pug'
});
canvas.add(clipRect1);
var clipRect2 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 10,
top: 10,
width: 150,
height: 150,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 0,
selectable: false
});
// We give these `Rect` objects a name property so the `clipTo` functions can
// find the one by which they want to be clipped.
clipRect2.set({
clipFor: 'logo'
});
canvas.add(clipRect2);
function findByClipName(name) {
return _(canvas.getObjects()).where({
clipFor: name
}).first()
}
// Since the `angle` property of the Image object is stored
// in degrees, we'll use this to convert it to radians.
function degToRad(degrees) {
return degrees * (Math.PI / 180);
}
var clipByName = function (ctx) {
this.setCoords();
var clipRect = findByClipName(this.clipName);
var scaleXTo1 = (1 / this.scaleX);
var scaleYTo1 = (1 / this.scaleY);
ctx.save();
var ctxLeft = -( this.width / 2 ) + clipRect.strokeWidth;
var ctxTop = -( this.height / 2 ) + clipRect.strokeWidth;
var ctxWidth = clipRect.width - clipRect.strokeWidth;
var ctxHeight = clipRect.height - clipRect.strokeWidth;
ctx.translate( ctxLeft, ctxTop );
ctx.rotate(degToRad(this.angle * -1));
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
ctx.rect(
clipRect.left - this.oCoords.tl.x,
clipRect.top - this.oCoords.tl.y,
clipRect.width,
clipRect.height
);
ctx.closePath();
ctx.restore();
}
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 45,
width: 500,
height: 500,
left: 230,
top: 50,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
return _.bind(clipByName, pug)(ctx)
}
});
canvas.add(pug);
};
pugImg.src = img02URL;
var logoImg = new Image();
logoImg.onload = function (img) {
var logo = new fabric.Image(logoImg, {
angle: 0,
width: 550,
height: 190,
left: 50,
top: 50,
scaleX: 0.25,
scaleY: 0.25,
clipName: 'logo',
clipTo: function(ctx) {
return _.bind(clipByName, logo)(ctx)
}
});
canvas.add(logo);
};
logoImg.src = img01URL;
I hope this might help.
Having trouble getting the modified rotational angle of fabic.js object retaliative to is original angle/position.
I'm using .getAngle(), If the object is rotated more than 360 degrees or rotated back and forth I'm having trouble converting this back to an angle in degrees relative to it original position/rotation.
var canvas = new fabric.Canvas('canvas');
//global canvas setting
canvas.selection = false;
canvas.setDimensions({
width: 500,
height: 310
});
//Canvas Objets
// create a rectangle with angle=45
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 40,
height: 40,
lockUniScaling: true,
centeredRotation: true
});
canvas.add(rect);
//Object modification event
canvas.on('object:modified', function(e) {
var activeObject = e.target;
document.getElementById('result').value = activeObject.getAngle();
});
I've setup a fiddle showing the default output http://jsfiddle.net/1db5g7us/
I'm assuming in need to do some calculation on the result, but can't figure out what.
Just solved this one, all i needed to do was use the modulus operator to get the rotation relative to its original position rather than the total rotated angle.
activeObject = activeObject%360;
update the fiddle: http://jsfiddle.net/1db5g7us/
When I add a circle with an opacity lower than 1 to a group, its opacity becomes actually lower than the specified value. This does not happen if I don't specify opacity (i.e., opacity = 1). It also doesn't happen with a rectangle.
Here is the code to reproduce this issue:
HTML
<canvas id="stage" width="400" height="300">
JavaScript
var OPACITY = 0.65;
var FILL = '#fff';
var canvas = new fabric.Canvas('stage', {
backgroundColor: '#222'
});
/**
* Rectangles
* both appear to have the same color
*/
var rect1 = new fabric.Rect({
width: 40,
height: 40,
fill: FILL,
opacity: OPACITY,
left: 60,
top: 60
});
canvas.add(rect1);
var rect2 = new fabric.Rect({
width: 40,
height: 40,
fill: FILL
opacity: OPACITY,
});
var rect2Group = new fabric.Group([rect2], {
left: 120,
top: 60
});
canvas.add(rect2Group);
/**
* Circles
* the second circle is darker
*/
var circle1 = new fabric.Circle({
radius: 20,
fill: FILL,
opacity: OPACITY,
left: 60,
top: 120
});
canvas.add(circle1);
var circle2 = new fabric.Circle({
radius: 20,
fill: FILL,
opacity: OPACITY,
});
var circle2Group = new fabric.Group([circle2], {
left: 120,
top: 120
});
canvas.add(circle2Group);
Here is the JSFiddle.
If you run it, you can see that the second circle is darker than the first one, meaning that its opacity is lower.
Am I doing something wrong, or is this a bug? (Could be reproduced in 1.2.0 and 1.3.0.)
It's most likely because of this line in fabric.Circle:
// multiply by currently set alpha
// (the one that was set by path group where this object is contained, for example)
ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
This has to do with circles being part of SVG group, IIRC.
In any case, it's definitely a bug — the opacity shouldn't be multiplied in your case. We need to have a better check.
Please file an issue on github.