svg mask and bounding box - svg

I need to apply mask to a different objects.
Mask should cover whole object (visible part of it). I put the mask inside one specific place, at the top of the page, changed maskContentUnits to objectBoundingBox, so it worked perfectly.
But then a problem appeared.
I made a fiddle to illustrate the problem: http://jsfiddle.net/8qdt7vjr/1/
<body>
<svg width="0" height="0">
<defs>
<mask id="mask1" maskContentUnits="objectBoundingBox">
<ellipse cx=".5" cy=".5" rx=".5" ry=".5" fill="white" />
</mask>
</defs>
</svg>
<svg class="svg" width="200" height="150" overflow="visible">
<rect x="-50" y="-50" width="350" height="250" fill="none" stroke="green" stroke-width="2" />
<svg id="zzz" x="0" y="0" width="100%" height="100%" overflow="visible" mask="url(#mask1)">
<rect x="-50" y="-50" width="350" height="250" fill="blue" fill-opacity=".3" />
</svg>
<rect width="100%" height="100%" fill="red" fill-opacity=".1" stroke="red" stroke-width="1" />
</svg>
</body>
In this fiddle i want to apply mask to svg element with id="zzz". But inside this element there is a rect element, that increases zzz's bounding box. In the fiddle it is rect, but in my project it is an image tag. zzz has overflow set to hidden (in the fiddle I changed it to visible, so it is easier to see the problem), so I have a specific portion of image visible inside zzz.
The real problem is that zzz's inner content increases zzz's bounding box.
In the fiddle I want ellipse mask to be inside red rectangle (visible zzz's area), but it is inside green rectangle (zzz's bounding box) instead.
So the main question is: is there any way to achieve this goal? Mask will be used by many elements with different sizes and content and I do not want to clone it.
Is there any way to do this without cloning mask inside each element?
Is there any way to reduce bounding box to visible area?
Is there any way to show a part of an image without expanding parent's bounding box?
Is there any other way to do this?

Is it something like this you try to achieve?
<body>
<svg width="0" height="0">
<defs>
<mask id="mask1" maskContentUnits="userSpaceOnUse">
<ellipse cx="100" cy="75" rx="100" ry="75" fill="white" />
</mask>
</defs>
</svg>
<svg class="svg" width="200" height="150" overflow="visible">
<rect x="-50" y="-50" width="350" height="250" fill="none" stroke="green" stroke-width="2" />
<svg id="zzz" x="0" y="0" width="100%" height="100%" overflow="visible" mask="url(#mask1)">
<rect x="-50" y="-50" width="350" height="250" fill="blue" fill-opacity=".3" />
</svg>
<rect width="100%" height="100%" fill="red" fill-opacity=".1" stroke="red" stroke-width="1" />
</svg>
</body>
Maybe using userSpaceOnUse instead of objectBoundingBox can help achieve what you want... In combination with nested svg elements you can define the userspace to use and with that the part the mask is applied to...

Related

(SVG) Transform origin of grouped path element is not getting applied

I want to define grouped shapes in the <def> section and display them via the <use> tag with the transformation-origin being the group's center. Following is a minimal example illustrating my issue:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
<defs>
<g id="triangle">
<path fill="green" d="m 24 0 l 24 41.569 l -48 0 z" />
<circle cx="24" cy="24" r="1" fill="red" />
<rect width="48" height="41.569" fill="purple" fill-opacity="20%" />
</g>
</defs>
<rect width="100" height="100" />
<rect fill="gray" x="100" width="100" height="100" />
<rect width="100" height="100" />
<rect fill="gray" y="100" width="100" height="100" />
<rect width="100" height="100" x="100" y="100" />
<use href="#triangle" transform-origin="50% 50%" transform="translate(100 100)" />
</svg>
As it is my understanding, the triangle should be centered in the background. But in actuality, the top left corner of the group is centered.
I have tested my example against the MDN transform-origin one. The MDN one works well in the same environment (Edge Browser & VSCode). This lets me believe I am missing some side effects of the used tags or attributes
Observed behavior
Expected behavior
A scale transform has a centre point i.e. a point that doesn't change position.
So does a rotation - there's a centre of rotation.
A translate transform does not, every location moves. There's therefore no origin so transform-origin does nothing.

how to do svg transform in percentage

I want to center the rect shape with something equivalent to
transform="translate(50% - 100,0)" for example:
<svg width="100%" height="100%" viewbox="0 0 100% 100%">
<g transform="translate(50% - 100,0)">
<rect width="200" height="100" fill="rgb(0,0,255)" />
</g>
</svg>
I can't find the right syntax.
You can use an inner <svg> element to do the percentage part via its x attribute then the rest with the <g> element as you already have.
I'm not sure what you intend with the viewBox but percentage values are not valid there. Looks like you just don't need that at all.
<svg width="100%" height="100%">
<svg x="50%" overflow="visible">
<g transform="translate(-100,0)">
<rect width="200" height="100" fill="rgb(0,0,255)" />
</g>
</svg>
</svg>

SVG how to set max width for group

I have some SVG elements grouped together in a <g> element (exactly the barcode 1D, PHP generates a barcode).
<g
style="fill:#000000;stroke:none"
id="barcode1D"
transform="matrix(1.2083333,0,0,0.8247805,62.027778,573.54235)">
<rect
x="0"
y="0"
width="4"
height="30"
id="xyz" />
....
<rect
x="224"
y="0"
width="0"
height="30"
id="xyzn" /> </g>
The barcode is generated in various widths, lengths. How can I set the width permanently ?
Based on this example, I am asking for a hint. Thank you for your help in advance.
SVG g element does not have width and height attributes. Therefore, you can not set height and width on it.
You should use a foreignObject with a svg inside of it to do so.
<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
<foreignObject id="G" width="300" height="200">
<svg>
<!-- Barcode here -->
<rect fill="black" stroke-width="2" height="112" width="84" y="55" x="55" stroke="#000000"/>
<circle fill="#FF0000" stroke="#000000" stroke-width="5" cx="155" cy="65" id="svg_7" r="50"/>
</svg>
</foreignObject>
</svg>

Use <use> within <clipPath> in <defs>

Can I use <use> to refer to a previously declared object inside a <clipPath> declaration?
So that it uses that element as definition for the clip path?
For example:
<defs>
<rect id="foo" width="20" height="20" />
<clipPath id="bar">
<use href="#foo" />
</clipPath>
</defs>
Yes, you can use the <use> command inside the clipPath declaration to refer to any external objects inside the svg file.
In the example below, clipPath cuts a 80 x 80px square from the image.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 300" style="border:1px solid red">
<defs>
<rect id="foo" width="80" height="80" />
<clipPath id="bar">
<use href="#foo" />
</clipPath>
</defs>
<image clip-path="url(#bar)" xlink:href="http://lorempixel.com/600/600/nature/1" x="20" y="20" height="100%" width="100%" />
</svg>
The red square shows the border of the entire canvas svg.

How to interpret graph-paper generating svg?

I need help interpreting the svg which generates this graph paper.
I think I understand the general idea behind the code:
there are 3 layers/groups being created, one of which has the original rectangle
translation and transform operations appear to be used to replicate this rectangle all over the canvas.
but I'm having a hard time understanding some details behind the svg code.
I also don't understand how the layers interact with each other.
Questions
How do you interpret the transform="matrix(0,1,-1,0,400,0)" operation?
Can you explain the implied for-loop that's in this svg code which copies the rectangles?
What does the path tag do in the context of this code?
I am trying to understand this svg code well enough so I can modify it for my own uses.
Thank you.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0"
width="400"
height="400"
id="svg2180">
<defs
id="defs2182" />
<g
style="opacity:1;display:inline"
id="layer1">
<g
style="stroke:#a9a9a9;stroke-opacity:1"
id="g8191">
<path
d="M 20,0 L 20,400"
style="fill:none;fill-rule:evenodd;stroke:#a9a9a9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path1872" />
<use
transform="translate(20,0)"
style="stroke:#a9a9a9;stroke-opacity:1"
id="use8185"
x="0"
y="0"
width="400"
height="400"
xlink:href="#path1872" />
<use
transform="translate(40,0)"
style="stroke:#a9a9a9;stroke-opacity:1"
id="use8187"
x="0"
y="0"
width="400"
height="400"
xlink:href="#path1872" />
<use
transform="translate(60,0)"
style="stroke:#a9a9a9;stroke-opacity:1"
id="use8189"
x="0"
y="0"
width="400"
height="400"
xlink:href="#path1872" />
</g>
<use
transform="translate(100,0)"
id="use8197"
x="0"
y="0"
width="400"
height="400"
xlink:href="#g8191" />
<use
transform="translate(200,0)"
id="use8199"
x="0"
y="0"
width="400"
height="400"
xlink:href="#g8191" />
<use
transform="translate(300,0)"
id="use8201"
x="0"
y="0"
width="400"
height="400"
xlink:href="#g8191" />
<use
transform="matrix(0,1,-1,0,400,0)"
id="use8203"
x="0"
y="0"
width="400"
height="400"
xlink:href="#g8191" />
<use
transform="translate(0,100)"
id="use8205"
x="0"
y="0"
width="400"
height="400"
xlink:href="#use8203" />
<use
transform="translate(0,200)"
id="use8207"
x="0"
y="0"
width="400"
height="400"
xlink:href="#use8203" />
<use
transform="translate(0,300)"
id="use8209"
x="0"
y="0"
width="400"
height="400"
xlink:href="#use8203" />
</g>
<g
style="display:inline"
id="layer2">
<g
style="stroke:#366;stroke-opacity:1"
id="g8225">
<path
d="M 100,0 L 100,400"
style="fill:none;fill-rule:evenodd;stroke:#366;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path8215" />
<use
transform="translate(100,0)"
style="stroke:#366;stroke-opacity:1"
id="use8217"
x="0"
y="0"
width="400"
height="400"
xlink:href="#path8215" />
<use
transform="translate(200,0)"
style="stroke:#366;stroke-opacity:1"
id="use8219"
x="0"
y="0"
width="400"
height="400"
xlink:href="#path8215" />
</g>
<use
transform="matrix(0,1,-1,0,400,0)"
id="use8232"
x="0"
y="0"
width="400"
height="400"
xlink:href="#g8225" />
</g>
<g
id="layer3">
<rect
width="399"
height="399"
x="0.5"
y="0.5"
style="fill:none;stroke:#366;stroke-opacity:1"
id="rect10078" />
</g>
</svg>
Don't misinterpret the "layers" in this document. They aren't really about layering, they're about grouping.
How do you interpret the transform="matrix(0,1,-1,0,400,0)" operation?
That is a transformation matrix for an affine transform. It's a fancy way to combine rotation, skew, and translation into one function. They can be difficult to wrap one's mind around though, and I usually only see them used in code generated by a drawing application.
Can you explain the implied for-loop that's in this svg code which copies the rectangles?
In SVG, you can re-use any object that you have given an id to, using the <use .../> tag. This can be used as a sort of DRY, to keep repetition low in the code. In this case, a group of horizontal lines is created, then copies are made by referencing them with use tags. each use has it's own transform attribute to move it into place. Halfway down the list, the line group get rotated 90 degrees (using the transform matrix) and then copied across the image.
What does the path tag do in the context of this code?
It just draws the thick line. This could have been done with a line element, but drawing software output that, and it wasn't smart enough to replace it, I guess. Usually path elements are used for more complex shapes, since they support arcs and bezier curves.

Resources