Shared coordinates between elements in SVG - 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>

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).

Can an SVG element be allowed to overflow its mask?

Currently working on a project that uses a slider to compare two different images overlaid with SVG's. SVG's on the right side of the slider have a mask applied to them while the SVG's on the left should remain unchanged.
My problem is that when using a mask to apply these styles the mask clips any of the element that it doesn't cover.
Reproduction CodePen: https://codepen.io/anon/pen/VNEOPy
Super minimal repro:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" height="200px">
<defs>
<pattern
id="pattern"
width="10"
height="10"
patternUnits="userSpaceOnUse"
>
<circle cx="5" cy="5" r="5" fill="#999"></circle>
</pattern>
<mask id="masker">
<rect x="0" y="0" width="25%" fill="url(#pattern)"></rect>
</mask>
</defs>
<circle cx="50" cy="50" r="50" mask="url(#masker)"></circle>
</svg>
What I would like to do is apply the mask to the portion of the element that the mask covers and allow the rest of the element to remain visible/unchanged.
This CodePen demonstrates the behavior I am looking for, but requires duplicating each of the SVG's (which is unfortunately not technically feasible in my case): https://codepen.io/anon/pen/vMzwbP
Is there a way to achieve this behavior with masking? Am I looking in the wrong place?
No. You are always going to have to have two instances of the circle. One with the mask applied, and one with no mask (or the inverse mask).

SVG fills in external file

Really basic SVG question. I have read
SVG sprite in external file
and it works fine for me to add a svg graphic, but I can't get it to work with defs. First the file 'defs.svg':
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs id='patternDefs'>
<pattern id="pattern1"
x="2" y="2"
width="5" height="5"
patternUnits="userSpaceOnUse" >
<circle cx="2" cy="2" r="2" class="blue" />
</pattern>
</defs>
</svg>
and then the svg in a separate file:
<svg>
<use xlink:href="defs.svg#patternDefs"></use>
<circle cx="15" cy="15" r="50" stroke-width="2" stroke="red" fill="url(#pattern1)" />
</svg>
I am looking to get the fill="url(#pattern1)" part to work, as that is what is referencing the def in the external file.
Sorry if you think this has been answered elsewhere but I've read a ton of stuff and thought that if I could get the sprite version to work then why not a defs version. (I am very new to svg)
xlink:href="defs.svg#patternDefs" should be xlink:href="defs.svg#pattern1"
On top of that <use> has to point to something to be rendered, not a pattern. If you want to fill a circle with a pattern just set the circle's fill to the pattern. E.g.
<svg>
<circle cx="80" cy="80" r="50" stroke-width="2" stroke="red" fill="url(defs.svg#pattern1)" />
</svg>
Note that external fills are not widely supported, although they do work on Firefox for instance.

Putting coordinate location markers in an 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.

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