Stretch and rotate particular part of SVG image - javascript

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>

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.

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.

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

Changing Clickable Area of an Image without Resizing Image

I am currently working on a PHP/Javascript project where an action occurs when an image is clicked. The image is small, so I would like to expand the clickable area to further around the image without enlarging the image itself. Is this possible? Below is a general idea of the structure of what I'm working on.
<g id="pictures">
<image id="marker_image" cx="145" cy="460" r="1" preserveAspectRatio="none"
x="136" y="451" width="18" height="18"
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="//link.thislink.com/image_assets/markers/pool.png"
style="opacity: 1" fill="#000000" fill-opacity="1" stroke="#000000"
stroke-opacity="1" stroke-width="2" stroke-linecap="round" stroke-
linejoin="round"></image>
</g>
I'm new to working with SVGs, but from what I've read, I think I can use the <g> to add padding?
Wrap you image in a div, make the div as big as you want using padding, and bind your action on the div instead of the img

Categories