Get a single path value for svg file having multiple paths - javascript

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.

Related

Load external SVG icons into vanilla JavaScript code

I am using the OpenWeather API to display the current and five day forecast on my client's website.
I have some custom SVG icons that I want to use instead of the icons provided by OpenWeather. I have implemented the following switch statement to display a different icon depending on the weather condition.
let dailyCondition = value.weather[0].description;
let dailyCondtionIcon = "";
switch (dailyCondition) {
case "clear sky":
dailyConditionIcon = `<svg>icon</svg>`;
break;
case "few clouds":
dailyConditionIcon = `<svg>icon</svg>`;
break;
case "thunderstorm":
dailyConditionIcon = `<svg>icon</svg>`;
break;
case "light rain":
dailyConditionIcon = `<svg>icon</svg>`;
break;
}
Accessing the icons from template literal code works, but with lots of weather conditions in the switch statement, the code is very bloated. I would like to have the SVG icons stored in an external file and loaded from there.
How would I go about loading the external SVG icons into my vanilla JavaScript file?
If you prefer external svg files you could load them in a <use> element.
See also SVG use with External Source
You can combine all svg icons to a single sprite/asset library svg file and then loading each icon individually by a fragment identifier:
You js definitions might look something like this:
dailyConditionIcon = '<svg class="svgInline" fill="red" ><use href="sprite.svg#circle" /></svg>'
.svgAssets{
display:none
}
.svgInline{
display:inline-block;
width:1em;
height:1em;
font-size:32px;
}
<!-- this would be the content of your "sprite.svg" -->
<svg class="svgAssets" xmlns="http://www.w3.org/2000/svg">
<symbol viewBox="0 0 100 100" id="circle">
<circle cx="50%" cy="50%" r="50%"></circle>
</symbol>
<symbol viewBox="0 0 100 100" id="rect">
<rect x="0" y="0" width="100" height="100"></rect>
</symbol>
<symbol viewBox="0 0 100 100" id="rectFixedStyle">
<rect x="0" y="0" width="100" height="100" fill="#ccc"></rect>
</symbol>
</svg>
<!--
for demonstration the filenames are dropped.
The href of a hosted version would be e.g
<use href="sprite.svg#circle" />
-->
<p>
<svg class="svgInline" fill="red" >
<use href="#circle" />
</svg>
<svg class="svgInline" fill="green" >
<use href="#rect" />
</svg>
<svg class="svgInline" fill="green" >
<use href="#rectFixedStyle" />
</svg>
</p>
As you can see you also have some styling abilities like changing fill color.
However the styling options are limited (compared to fully inlined svg) and also depend on your svg structure:
E.g. Styles previously definded in your svg elements can't be overriden by a style set in use/svg tag.
For sprite creation I used: svgsprit.es

SVG make different sections of the path in different colors

I have been trying to implement the following requirements.
1. SVG path to have multiple colors on different sections (eg - red color the curves and rest of it, in black color)
2. Only allow mouse event- click on those colored areas (curves)
I have tried with plain javascript and snap.svg
Plain html & Javascript
[Codepen using HTML & Js][1]
SNAP.svg
[Codepen using SNAP.svg][2]
[1]: https://codepen.io/sanathko1234/pen/vvMQQZ
[2]: https://codepen.io/sanathko1234/pen/OrGoRa
How can this be achieved?
One solution would be to use the path twice: first the green one and next the one using stroke-dasharray. The dashes are only over the curves. If you don't like the position or the length of the dashes change them to what you need. The gaps are not sensitive to mouse events, only the dashes are.
In css I've added #gold:hover{cursor:pointer} so that you can see that only the dashes are sensitive to the mouse.
I hope it helps.
svg{border:1px solid}
use{fill:none;stroke-width:18;}
#gold:hover{cursor:pointer}
<svg viewBox="-10 50 580 360" width="580" height="360" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="svg_1" d="m555,272c1,0.76736 4,85.76736 -71,97.76736c-75,12 -387,-39 -388,-39.76736c0,-0.23264 -29,-1.23264 -45,-21.23264l-42,-124.76736c-3,-11.23264 -3,-21.23264 3,-26.23264c6,-5 46,-67 69,-69.76736l474,184z" />
</defs>
<g>
<title>background</title>
<rect fill="#fff" id="canvas_background" height="360" width="580" x="-10" y="50"/>
</g>
<g>
<title>Layer 1</title>
<use xlink:href="#svg_1" stroke="green" />
<use xlink:href="#svg_1" stroke="gold" stroke-dasharray ="130 370 110 60 90 40 90 400 52.45" id="gold" pointer-events="stroke" />
</g>
</svg>
Observation: the sum of the dashes and the gaps is 1342.45 which is also the total path length.

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

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.

SVG html5 draw characters

Let's say I have to refactor some code and change it.
I have an svg object that looks like this:
<svg>
<g>
<path xmlns="http://www.w3.org/2000/svg" fill="#FFFFFF" d="M267.2,605.4l0.5-4l-1.1-0.6l0.2-1l2.7-0.6l0.5,0.3l-0.8,6c-0.2,1.3-0.3,2.2-0.3,3.3 c0,1.5,0.6,1.9,1.6,1.9c1,0,2.1-0.7,2.8-1.4l1.3-10h2.1l-1.4,10.6c-0.1,0.6,0,0.8,0.2,0.8c0.2,0,0.5-0.1,1.2-0.7l0.3,0.6 c-0.2,0.3-1.4,1.6-2.7,1.6c-0.9,0-1.4-0.6-1.2-1.5c-0.8,0.8-2,1.5-3.6,1.5c-1.7,0-2.8-0.7-2.8-3 C266.8,608.2,267,606.7,267.2,605.4z"/>
</g>
</svg>
As an out put here I get the letter "U".
So how can write in such manner anything for example I want to write "stackoverflow" using this technology?

Stretch and rotate particular part of SVG image

I'm making a web interactive test for musicians, and got stuck up on, well, interactiveness.
Users are supposed to move notes on a stave and adjust them.
SVG pathes are rendered as notes, with a separate parent div container for each note. Parent div is dragged on to the stave, and then can be resized ( I'm using jQuery UI for this, with option "handles" set to "e", so div can be resized only to the right). After this point I can not figure out how to correctly resize the SVG note inside it, because what needed to be resized, is not the whole SVG, but just one part.
SVGs look like this:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="32" viewBox="0 0 24 32" class="svgnote" preserveAspectRatio="none">
<path d="M0 23.703q0-0.922 0.672-1.797 0.313-0.344 0.766-0.711t1-0.727q0.531-0.25 1.031-0.359t0.953-0.109q0.953 0 1.688 0.531v-17.344h13.578v18.797q0 0.953-0.641 1.781-0.641 0.875-1.703 1.352t-2.047 0.477q-0.859 0-1.563-0.516t-0.703-1.375q0-0.984 0.703-1.797 0.609-0.797 1.719-1.438 0.578-0.25 1.055-0.359t0.93-0.109q0.969 0 1.703 0.531v-15.188h-12.484v16.641q0 0.953-0.641 1.781-0.641 0.875-1.695 1.352t-2.055 0.477q-0.891 0-1.594-0.516-0.672-0.516-0.672-1.375z"></path>
</svg>
Picture example
I added a picture, where above red figure
it's an initial state of a note;
upper red arrow is pointing out on a line, which is the only part of svg that needs to stretch out to the right.
lower red arrows aside -- the note should (somehow?) be rotated up and down, to make 3rd state possible
is what final state of note I'm looking for.
What I have done:
except excessive googling, not much. I tried to set "width" of SVG image to "100%" of the parent div, and add preserveAspectRatio="none", but all I got is ugly stretched note.
As for rotation I do not have even a single idea from what should I start.
I'd be eternally grateful if someone point out for what should I google, or maybe a library should I use. I'm sensing a solution to this is close somewhere, I'm just missing it because of my very limited experience in the field.
Thank you all.
Here's a 10mins hack. Connecting bar needs more work but the gist is use a collection of <symbol>for your musical notation and a better path (eg: polygon?) for the connecting bar.
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="note-1" viewBox="0 0 313 340">
<g xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,-1,313,340)" id="g11029">
<path d="M 303.13715,299.65106 C 299.74131,301.47103 297.93187,304.76561 299.04493,307.24402 C 300.23219,309.88766 304.31194,310.63374 308.15151,308.90939 C 311.99107,307.18503 314.14367,303.63999 312.95641,300.99636 C 311.76914,298.35272 307.6894,297.60664 303.84983,299.33099 C 303.60986,299.43876 303.36355,299.52973 303.13715,299.65106 z " style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path11031"/>
<path d="M 299.50465,305.98445 L 299.50465,339.57202" style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path11033"/>
</g>
</symbol>
<g class="first" transform="translate(0,20)">
<use xlink:href="#note-1" />
</g>
<g class="second" transform="translate(30,10)">
<use xlink:href="#note-1" />
</g>
<path stroke-width="4" stroke="black" d="M87,20 L117,10"></path>
</svg>

Categories