I want to load different shapes in FabricJS based Canvas using loadSVGFromURL(), but can't. Documentation is also not complete on this. I just want a complete example. I can load it from string, but string creates spaces which creates problems when rendering. Here is my code:
var canvas = new fabric.Canvas('canvas');
fabric.loadSVGFromURL('BlueFlower.svg', function (objects) {
var SVG = fabric.util.groupSVGElements(objects, options);
canvas.add(SVG).centerObject(SVG).renderAll();
SVG.setCoords();
});
I have done an example on jsfiddle, that I create two objects and I load an svg image from url, you can take a look.
Here is an example
The snippet for load svg is this:
var site_url = 'http://fabricjs.com/assets/1.svg';
fabric.loadSVGFromURL(site_url, function(objects) {
var group = new fabric.PathGroup(objects, {
left: 165,
top: 100,
width: 295,
height: 211
});
canvas.add(group);
canvas.renderAll();
});
Related
I'm trying to display more than 6000 Polygons on a mobile device.
Currently, I'm doing this with SVG paths in Android WebView using the d3.js library.
It works but I have to deal with performance issues, my map becomes very laggy when I drag my map or zoom.
My Idea now is to try the same with pixijs. My data comes originally from ESRI Shapefiles. I'm convert these Shapefiles to GeoJSON and then to SVG. My array of vertices looks like this, which I'm trying to pass to the drawPolygon function
0: 994.9867684400124
1: 22.308409862458518
2: 1042.2789743912592
3: 61.07148769269074
But when I try to render these polygon nothing being displayed. This is my code:
var renderer = PIXI.autoDetectRenderer(1800, 1800, { backgroundColor: 0x000000, antialias: true });
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
var graphics = new PIXI.Graphics();
var totalShapes = feat.features.length;
for (var i = 1; i <= totalShapes -1; i++) {
var shape = feat.features[i];
var geometry = shape.geometry.bbox;
graphics.beginFill(0xe74c3c);
graphics.drawPolygon([ geometry]);
graphics.endFill();
stage.addChild(graphics);
renderer.render(stage);
}
Can someone help me or could suggest me a different way?
I have not seen that way of initializing a pixie project.
Usually you add the application to the html document like:
var app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);
If you do this you can add your draw calls to the setup of the application:
app.loader.load(startup);
function startup()
{
var g = new PIXI.Graphics();
g.beginFill(0x5d0015);
g.drawPolygon(
10, 10, 120, 100, 120, 200, 70, 200
);
g.endFill();
app.stage.addChild(g);
}
This will render the polygon once.
I'm using loadSVGfromURL to fill a canvas with this SVG
As you can see in the link, I got some Heather effect on my shirt, along with some shadows. Plus, my SVG style applies a mix-blend-mode: multiply; to my paths.
Unfortunately, once rendered in my canvas, it seems like the paths CSS is not taken into account :
How can I make sure that this style is applied ?
Here is an exemple. Basically you need to map mix-blend-mode to globalCompositeOperation
var site_url = 'http://s3.eu-central-1.amazonaws.com/balibart-s3/SVGMockups2/59f32980b5d8493ef7f29904/front/Layer.svg';
canvas = new fabric.Canvas('canvas');
fabric.loadSVGFromURL(site_url, function(objects) {
var group = new fabric.Group(objects, {
left: 165,
top: 100,
});
canvas.add(group);
group._objects[3].globalCompositeOperation='multiply';
group._objects[2].globalCompositeOperation='multiply';
group._objects[4].globalCompositeOperation='multiply';
group._objects[5].globalCompositeOperation='multiply';
group._objects[6].globalCompositeOperation='multiply';
/*for(var i=0;i<objects.length;i++){
canvas.add(objects[i]);
}
canvas.getObjects()[5].globalCompositeOperation='multiply';*/
// canvas.add(objects);
canvas.renderAll();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.js"></script>
<canvas id='canvas' width="900" height="900"></canvas>
I'm importing several svgs that are all created from the same image and layered on top of each other. I would like to add text centered over a certain svg/textarea path. And then scale textarea to fit the text provided with a min size. And ive confused myself. I have no idea anymore? I deleted everything and started over direction would be very helpful. Heres what i got.
var canvas = new fabric.Canvas('canvas');
fabric.loadSVGFromURL('/1-man.svg', function(objects, options) {
var obj = fabric.util.groupSVGElements(objects, options);
canvas.add(obj).renderAll();
});
fabric.loadSVGFromURL('/1-man-cutout.svg', function(objects, options)
{
var obj = fabric.util.groupSVGElements(objects, options);
canvas.add(obj).renderAll();
});
fabric.loadSVGFromURL('/textarea.svg', function(objects, options) {
var obj2 = fabric.util.groupSVGElements(objects, options);
canvas.add(obj2).renderAll();
});
var text = new fabric.Text("Hello", {
fontFamily: 'ubuntu',
fontSize: 300,
textAlign: "center",
});
canvas.add(text);
Brain was dead i suppose.... took about a min this morning.. Ill keep it for a lesson on sleeping on it.
text.set('left', (objects[0].width - text.width)/2);
text.set('top', objects[0].top + 5);
canvas.add(obj2, text).renderAll();
could someone please point me in the direction for how to enable double click on fabric images? i came across this solution
FabricJS double click on objects
I am trying to not use FabicjsEx
but i am unable to get anything to work correctly. can someone please let me know the best way to accomplish this?
The best way to accomplish this, is to use fabric.util.addListener method.
Using that you could add a double click event for the canvas element and to restrict it to any particular object ( ie. image ), you would have to check whether you clicked on an image object or not before performing any action.
ᴅᴇᴍᴏ
var canvas = new fabric.Canvas('canvas');
// add image
fabric.Image.fromURL('https://i.imgur.com/Q6aZlme.jpg', function(img) {
img.set({
top: 50,
left: 50
})
img.scaleToWidth(100);
img.scaleToHeight(100);
canvas.add(img);
});
// add rect (for demo)
var rect = new fabric.Rect({
left: 170,
top: 50,
width: 100,
height: 100,
fill: '#07C'
});
canvas.add(rect);
// mouse event
fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function(e) {
if (canvas.findTarget(e)) {
const objType = canvas.findTarget(e).type;
if (objType === 'image') {
alert('double clicked on a image!');
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.js"></script>
<canvas id="canvas" width="320" height="200"></canvas>
I have a canvas built using fabricJS with the dimension of 600x500. I have added an image to this canvas which is of size 200x300 and also a text element just below it.
$canvasObj.toDataURL();
exports the whole canvas area including the white spaces surrounding the design on the canvas.
Is there a way to get the cropped output of the design on the canvas alone instead of all the whitespace?
This can be done by cloning objects to a group, getting the group boundingRect, and then passing the boundingRect parameters to toDataUrl() function (see fiddle).
e.g.
// make a new group
var myGroup = new fabric.Group();
canvas.add(myGroup);
// ensure originX/Y 'center' is being used, as text uses left/top by default.
myGroup.set({ originX: 'center', originY: 'center' });
// put canvas things in new group
var i = canvas.getObjects().length;
while (i--) {
var objType = canvas.item(i).get('type');
if (objType==="image" || objType==="text" || objType==="itext" || objType==="rect") {
var clone = fabric.util.object.clone(canvas.item(i));
myGroup.addWithUpdate(clone).setCoords();
// remove original lone object
canvas.remove(canvas.item(i));
}
}
canvas.renderAll();
// get bounding rect for new group
var i = canvas.getObjects().length;
while (i--) {
var objType = canvas.item(i).get('type');
if (objType==="group") {
var br = canvas.item(i).getBoundingRect();
}
}
fabric.log('cropped png dataURL: ', canvas.toDataURL({
format: 'png',
left: br.left,
top: br.top,
width: br.width,
height: br.height
}));
p.s. I should probably mention that i've not worked with image types, so i just guessed that it's called 'image'..