Exporting to SVG in fabric with svgs doesn't match canvas - javascript

We are using Fabric.js 1.7.20. We aren't able (yet) to update to 2.0+.
http://jsfiddle.net/tcem4f4L/
The issue is that we are adding SVG objects to the map, but when they get output to an svg, some padding within the SVG causes the rendering to not look correct. The svg x/y coordinates and any lines within them need to have the stroke accounted for.
I'm trying to figure out a clean way to handle these and ensure that the bounding box on the canvas is around the SVG for aligning purposes.
Example SVG:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="95" height="11" viewBox="0 0 95 11" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="currentColor" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="95" height="11"></rect>
<path stroke-linecap="square" stroke-width="3" d="M1,9 l93,0"/>
</g>
</svg>
So (I think) to fix it on output to SVG, I'd need to change the rect x and y to 0.5 and the path to d="M1.5,9.5 l93,0"
I am worried that there are other things in this I'm missing.

Related

Get a single path value for svg file having multiple paths

I am creating an icon component for which I am storing my icons as svg co-ordinates.
Eg:
trash: 'M192 1024h640l64-704h-768zM640 128v-128h-256v128h-320v192l64-64h768l64 64v-192h-320zM576 128h-128v-64h128v64z'
But certain svg icon files have multiple paths(like below). But I intend to have only one path value for storing my icon co -ordinates. Can someone please tell me what can I do to solve this?
<svg id="add-contact-communication-workflow-system-filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_822" data-name="Group 822" transform="translate(-938.662 -1091.778)">
<g id="Group_821" data-name="Group 821">
<path id="Path_821" data-name="Path 821" d="M948.432,1103.947a4.063,4.063,0,1,0-4.063-4.062A4.067,4.067,0,0,0,948.432,1103.947Z"/>
<path id="Path_822" data-name="Path 822" d="M948.432,1104.844a7.9,7.9,0,0,0-7.89,7.89,1.539,1.539,0,0,0,1.539,1.54h12.7a1.54,1.54,0,0,0,1.54-1.54A7.9,7.9,0,0,0,948.432,1104.844Z"/>
</g>
<path id="Path_823" data-name="Path 823" d="M960.033,1095.873h-1.84v-1.84a.75.75,0,0,0-1.5,0v1.84h-1.84a.75.75,0,0,0,0,1.5h1.84v1.84a.75.75,0,0,0,1.5,0v-1.84h1.84a.75.75,0,0,0,0-1.5Z"/>
</g>
<rect id="Rectangle_503" data-name="Rectangle 503" width="24" height="24" fill="none"/>
</svg>
here
As long as the paths have the same style, and none of them have a transform different from the others, you can simply append the paths together into one.
M948.432,1103.947a4.063,4.063,0,1,0-4.063-4.062A4.067,4.067,0,0,0,948.432,1103.947Z M948.432,1104.844a7.9,7.9,0,0,0-7.89,7.89,1.539,1.539,0,0,0,1.539,1.54h12.7a1.54,1.54,0,0,0,1.54-1.54A7.9,7.9,0,0,0,948.432,1104.844Z M960.033,1095.873h-1.84v-1.84a.75.75,0,0,0-1.5,0v1.84h-1.84a.75.75,0,0,0,0,1.5h1.84v1.84a.75.75,0,0,0,1.5,0v-1.84h1.84a.75.75,0,0,0,0-1.5Z
Note that the three paths, in your example SVG, are inside a group that has a transform. You may need to take account of that in your component if you want them to display in the correct place.
You have to get rid of transforms and groups first. Then only it can be done. you can try the 'https://www.npmjs.com/package/svgo' module to optimize the svgs and convert them into a single path. But again you have to get rid of groups and transforms.

How to set static SVG size for `<g id="child">` element under `<svg id="parent">` element that gets transform attr

Main Question:
Is there a way to set a static width and height on <g> elements so that they don't get effected by transform attribute done on its parent view-box <svg> element?
i.e.
<svg id="viewbox" transform="translate(1,5)scale(2)">
// continuously gets the transform attr via js upon zoom event
<g>
<path "the shape of a triangle"/>
<path same/>
<path same/>
<path same/>
<path same/>
</g>
</svg>
I want everything under the <g> element to translate according to the zoom event transform values that the <svg> view-box receives, but not scale the dimensions of the <g> element. So that it looks like the screen is zooming into one section of the view-box, but without the <g> elements changing dimensions.
Instead of applying transformations to the svg element tag (svg) directly, you can use a group tag (g) to translate everything and a rectangle tag (rect) to scale only your 'viewbox'.
<svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(1, 5)">
<rect
id="viewbox"
fill="black"
width="100"
height="100"
transform="scale(2)" />
<!-- your elements down here -->
<rect
fill="grey"
width="20"
height="20"
x="10"
y="10" />
</g>
</svg>
Hope this help :)

D3.js Text on path not rendered (no height / width)

I am trying to render circles which have a text inside, that runs along a given path.
The markup d3 produces looks fine, but Chrome is not showing the texts.
Upon inspection it says text elements have 0 width and 0 height.
This is sample markup including only two circles:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 950 600">
<g>
<g transform="translate(334.14792673070184,58.96385042366173)">
<defs>
<path id="path-1" d="m5,50 a45,45 0 0 0 90,0"></path>
</defs>
<circle class="circle" fill="#ccc" cx="50" cy="50" r="50"></circle>
<text fill="#333" font-size="15px">
<textpath xlink:href="#path-1" start-offset="0%">123456</textpath>
</text>
<use xlink:href="#path-1" fill="#666" opacity="0.1"></use>
</g>
</g>
<g transform="translate(374.66047394649974,371.7948729806046)">
<defs>
<path id="path-2" d="m5,50 a45,45 0 0 0 90,0"></path>
</defs>
<circle class="circle" fill="#ccc" cx="50" cy="50" r="50"></circle>
<text fill="#333" font-size="15px">
<textpath xlink:href="#path-2" start-offset="0%">123456</textpath>
</text>
<use xlink:href="#path-2" fill="#666" opacity="0.1"></use>
</g>
</svg>
When I inspect the markup in Chrome console and click "Edit as HTML" on the SVG element, make a random change, save & exit - the SVG suddenly renders correctly.
The exact same thing happens in Firefox and Opera.
Copy pasting the generated markup into a jsfiddle renders everything as expected.
I have tried pulling the < defs > tags out of each individual group into a single global < defs > but it did not solve the problem.
I have also looked at user-agent-stylesheet and other CSS rules that might interfere with rendering.
Is this a problem with how the SVG tag is included and/or the container element's width/height properties? I have been trying different things to fix this for a couple of hours now...
Here is the full SVG markup http://pastebin.com/J2Lz8p23
Here are the relevant parts in my code http://pastebin.com/Bym8kJVN

Resize polygon maintaining position - jQuery

So I have this svg that has multiple polygons inside, what I want to accomplish is to animate one polygon inside it (resize it with easing) such that it doesn't move from its place. Considering that the polygon position is set by points="..." (i guess..).
I want to do this preferably in jQuery or CSS but plain JavaScript works too or any other libraries..
Here is an example:
shapes.svg:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-47 49 404 404" style="enable-background:new -47 49 404 404;" xml:space="preserve">
<style type="text/css">
.st0{fill:#154E78;}
.st1{fill:#006496;}
.st2{fill:#047EBE;}
.st3{fill:#CD99B2;}
.st4{fill:#D464A4;}
.st5{fill:#CC78B1;}
</style>
<polygon id="XMLID_14_" class="st0" points="213.4,177 241.1,129 268.9,177 "/>
<polygon id="XMLID_13_" class="st1" points="240.2,129 212.4,177 184.7,129 "/>
<polygon id="XMLID_15_" class="st2" points="156,177 183.7,129 211.4,177 "/>
<polygon id="XMLID_20_" class="st3" points="98.6,177 126.3,129 154,177 "/>
<polygon id="XMLID_22_" class="st4" points="41.1,177 68.9,129 96.6,177 "/>
<polygon id="XMLID_29_" class="st5" points="125.3,129 97.6,177 69.8,129 "/>
</svg>
preview:
shapes.svg
what I want to accomplish is:
resized.svg
By resizing the 2nd polygon inside the svg
I dont have enough reputation to show you what happens if I scale it to 1.3 for example, but what happens is that the polygon moves along the artboard.
A simple scale transform (e.g. <polygon id="XMLID_29_" class="st5" points="125.3,129 97.6,177 69.8,129 " transform="scale(1.5)"/>) will scale the polygon points away from the origin. You want to scale the polygon points away from the center of the polygon. You can accomplish this using a transform that translates polygon center to origin, scales, and then translates polygon center back to initial location (e.g. <polygon id="XMLID_29_" class="st5" points="125.3,129 97.6,177 69.8,129 " transform="translate(97.55,153) scale(1.5) translate(-97.55,-153)"/>). In this example, I am using the center of the polygon's bounding rectangle as the center of the polygon (i.e.(125.3+69.8)/2=97.55, (129+177)/2=153).

SVG Grid lines are Blurred in Google Chrome while zooming but its work fine in Mozilla firefox

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1300" height="900" viewBox="0 0 750 300" id="mainsvg">
<g>
<defs>
<pattern x="0" y="0" width="1.6" id="smallGrid" height="1.6" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" id="smallgridbox" fill="none" stroke="rgb(8,24,77)" stroke-width="1"></path>
</pattern>
<pattern width="16" id="grid" height="16" patternUnits="userSpaceOnUse" x="687.47" y="0" shape-rendering="geometricPrecision">
<rect fill="url(#smallGrid)" width="16" height="16" fill-opacity="0.5"></rect>
<path d="M 100 0 L 0 0 0 100" id="largegridbox" fill="none" stroke="rgb(8,24,77)" stroke-width="1"></path>
</pattern>
</defs>
<rect fill="url(#grid)" width="1375" height="773" x="0" y="0" fill-opacity="0.5"></rect>
</g>
</svg>
Here is the JS Fiddle: http://jsfiddle.net/KashifMKH/L46j18fo/6/
It works fine in Mozilla Firefox, but not in Chrome. Zoom it at large and then compare the results in Mozilla and Chrome: you will see the difference clearly. How can I fix it?
I played around with your fiddle in chromium. That the gridlines become blurry if one zoomes in, appears also to me.
So I »manually« changed the viewBox in the html code so that the svg is scaled initially. Fiddle
Result: No blurry Gridlines.
So I think it is quiet obvious that chrom - e/ium does not rerender the pattern if the viewBox changes. You could try to update the viewBox by using the direct DOM-Binding:
var vb = a.viewBox.baseVal;
vb.x = ...
vb.y = ...
If that does not work I would try to use transforms and if that does not work, I think you cannot use <pattern> to create the grid and <use> elements, created by Javascript are the next option.

Categories