Putting coordinate location markers in an SVG - svg

I'd like to create a list of locations markers on an svg graphic that I can call upon, using the id, to place content at dynamically.
what is the best way of achieving this?
I'm thinking of using an empty def like this:
<defs>
<g id="coord"></g>
</defs>
<use xlink:href="#coord" id="L1" x="10" y="10" />
<use xlink:href="#coord" id="L2" x="100" y="100" />
Is there another way of doing this?
Is there any visual editor that can be used to generate use elements and assign ids?

I think a simpler approach would be to use something like:
<circle id="L1" cx="10" cy="10" r="0" />
Without a radius (and assuming there is no stroke-width in effect), they won't be visible.
And if you put them in their own group or layer in your Inkscape file, you can temporarily give them all a stroke-width or non-zero radius if you want to edit them. Then reset them back when you save the final version.

Related

Why can I only use SourceGraphic as in2 in a feDeformationMap?

If I use 'SourceGraphic' as in2 inside feDisplacementMap, things looks good. However, if I use anything else, the deformation is not applied.
Because of that, I have to define the deformation source first, and then apply the filter to the deformation source, which is quite counter-intuitive, at least for me.
For example, in the example below I have to define the circle and then apply the filter to the circle. Inside the filter I use feImage to load the kitten image. But that feels reverse to me. This works:
<svg>
<defs>
<filter id="displace">
<feImage href="https://placekitten.com/500/500" result="kitten" />
<feDisplacementMap
scale="10"
xChannelSelector="R"
yChannelSelector="R"
in="kitten"
in2="SourceGraphic"
/>
</filter>
</defs>
<circle cx="50" cy="50" r="50" fill="#f00" filter="url(#displace)" />
</svg>
As you can see, applying a displacement to a small part of an image becomes quite painful, as you have to first create the displacement map yourself, and it must have the same size as the image. Like this:
<g id="deformation-source" filter="url(#displace)">
<rect x="0" y="0" width={imageWidth} height={imageHeight} fill={neutralToDeformation} />
<circle cx="50" cy="50" r="50" fill="#f00" filter="url(#displace)" />
</g>
Also, applying 2 different deformations to the same image, requires you to put the objects that will cause the deformation, instad of doing something like this:
<image href="kitten-url" filter="url(#filter-1)" />
<image href="kitten-url" filter="url(#filter-2)" />
What I would like to be able to do is to load the kitten as an SVG image tag, and then apply the filter to that image, where I would load the circle inside a feImage making a reference to the object's id, which I would have previously defined inside the defs section. This doesn't work:
<svg>
<defs>
<circle id="displacement-source" cx="50" cy="50" r="50" fill="#f00" />
<filter id="displace">
<feImage href="displacement-source" result="displacement-source" />
<feDisplacementMap
scale="10"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="displacement-source"
/>
</filter>
</defs>
<image href="https://placekitten.com/500/500" width="100" filter="url(#displace)" />
</svg>
I'm not sure if I'm the one that's thinking this backwards or if I'm missing something. What's going on with this?
You can define your displacement source within the feImage, but it has to be an complete image defined as an inline URI in order to be cross browser compatible.
<feImage width="500" height="500" xlink:href="data:image/svg+xml,%3Csvg width='247' height='34'etc. etc.
Please see this article for more detail on how to escape characters in the svg+xml format - as far as I can remember there are some gotchas vs. vanilla HTML escaping.
If you don't care about Firefox, you can use a fragment identifier instead of inlining a whole SVG.
<feImage width="500" height="500" xlink:href="#idOfElementYouWantToUse"/>
Also remember that there are cross-origin security rules on displacementMap sources - so you can't displace an image using a map from another domain (or vice versa - I'm a little hazy on which way the restrictions run).

Responsive SVG sprites

I am building an icon system for a site and moving away from png and font-icon sprites to SVG.
I need it to work across all major browsers (IE9+) and ideally want to use fragment identifiers or, as a second best alternative, inline. I've done extensive research, and there isn't a great deal out there, and from what I have read SVG sprites aren't particularly responsive.
For fragment identifiers, using img tag, I have to set the width/height to the same size as the viewbox. Increasing the dimensions on the img tag ends up revealing some of the next sprite. I'd like to be able to use percentage values so the sprite fragment fills the parent container.
I just want confirmation that this isn't possible, I can't find anything that suggests I am wrong to think this.
This is very much possible and is relatively easy to accomplish. SVG's are vector graphics and therefore, if done correctly, will be the most responsive graphics on your website.
Set your SVG file up as expected but put each sprite into a <g> tag with its own identifier.
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="sprite" id="circle">
<ellipse cy="50" cx="50" ry="45" rx="45" stroke-width="5" stroke="#00ff00" fill="#00ff00" fill-opacity="0.75" />
</g>
<g class="sprite" id="square">
<rect y="5" x="5" width="90" height="90" stroke-width="5" stroke="#ff0000" fill="#ff0000" fill-opacity="0.75" />
</g>
<g class="sprite" id="triangle">
<path d="M20,7 L92,50 L6,93 z" stroke-width="5" stroke="#0000ff" fill="#0000ff" fill-opacity="0.75" />
</g>
</svg>
Add some CSS to say only the rargeted one needs to be displayed
<defs>
<style><![CDATA[
.sprite { display: none; }
.sprite:target { display: inline; }
]]></style>
</defs>
Then you can just call these out whenever required using an img tag or background element etc.
You can find the fully explained writeup here:
How to Use SVG Image Sprites

Shared coordinates between elements in SVG

I would like to share coordinates between two or more elements.
My example in peudo-Code :
<point xml:id="myPoint" x="10" y="20" />
<circle point="url(#myPoint)" r="10" />
<circle point="url(#myPoint)" r="50" />
I've seen IRI references that have the best match with that I searched, but :
First, there is no nodes of type "point" existing.
Second, IRI references doesn't support any attributes.
With SVG format and specifications (no javascript code), Is there a way to have many elements which reference the same coordinates ?
Thus, I just have to manipulate the point "myPoint" to change the coordinate of all elements that reference it.
I hope my english isn't so bad and thanks for your answers.
Use a group <g> element to transform the origin. If you omit co-ordinates then objects will be drawn there.
<g transform="translate(10, 20)">
<circle r="10" />
<circle r="50" />
</g>

Enforce relative links to defs in SVG

I'm trying to draw multiple SVGs on a single page and the ids in the defs section of each SVG are clashing. I'd like each one to refer only the mask in their own defs. Currently they all use the mask that has a matching id on the first svg on the page. No svg knows about the others so they would have to rely on a random number generator to pick ids that (hopefully) are different.
Is that possible or do they need unique ids if the SVGs are loaded into the same webpage. They are created on the fly by d3.
<svg>
<defs>
<mask id="temperatureMask">
<rect width="100%" height="100%" fill="#ffffff">
</mask>
</defs>
<rect mask="#temperaureMask">…etc
</svg>
<svg>
<defs>
<mask id="temperatureMask">
<rect width="100%" height="50%" fill="#dddddd">
</mask>
</defs>
<rect mask="#temperaureMask">…etc
</svg>
The ids on a page must be unique. That includes any inline SVGs. You will need to alter your d3 script like you suggest to add a unique number etc to the ids.

Can I apply clipping in SVG without specifying a clip-path ID?

In my markup, I have a chunk like this:
<svg width="0" height="0" style="display:none" id="dummy-wedge">
<g class="dummy" transform="translate(100, 100)">
<defs>
<clipPath id="clip1">
<polygon id="clip1Shape" points="-100,-100 0,-100 0,0 -100,-20" />
</clipPath>
</defs>
<circle id="" cx="0" cy="0" r="52" fill-opacity="0"
stroke="#ffffff" stroke-opacity="0.6" stroke-width="50"
pointer-events="visiblePainted" clip-path="url(#clip1)" />
</g>
</svg>
What I'm wanting to do is grab that chunk and clone it into a different svg root element to create a bunch of wedges, each with a different position and clip segment. That part is cool, but the frustration is that each cloned clipPath element will need to receive a new ID which will then have to be inserted into the clip-path attribute of the matching element.
I know that if all the arcs were the same length, I could have a common clip and use rotate transforms, but they aren't necessarily the same length.
Is it possible to declare a clip polygon using a topological relationship rather than by explicitly naming it? Alternatively, is there a better way to define an arc like this outside of using paths?
Thanks.
Why do you need to use clipping? Couldn't you just use path elements with the various arc segments in them?
There's no declarative way (yet) to get the behaviour you are after, but this is what the SVG Parameters specification is meant to address. Look at the examples there and the script implementation provided for processing the content (as a way to support the current browsers). NOTE: it's still a working draft, and is subject to change.

Resources