Is it possible to use SVG foreignObject as a mask? - svg

The text element inside the mask works as expected, but the div inside the foreignObject element is ignored.
<svg width='500' height='300' >
<defs>
<mask id='m'>
<text fill='white' x='0' y='35' font-size='35'>text element</text>
<foreignObject width='200' height='200' >
<div style='color:white;'>div element</div>
</foreignObject>
</mask>
</defs>
<rect width='200' height='200' mask='url(#m)' />
</svg>
Does anyone know how to get the foreignObject to work inside a mask? Is it even possible?

Related

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.

SVG text element not positioning correctly

I've set up a minimalist example of what I have here. I need to position the text element at the very top of the SVG. However if you inspect the text element, you'll see that it actually starts somewhere outside the SVG (like -3px on Chrome, -4px on FF) -- see below screenshot. I'm building something which needs to be pixel-perfect, so I need to get the text to start exactly where the SVG starts. As you can see, the rect starts where it's supposed to.
Since SO won't let me post links to jsfiddle without code inside the post, here's the code:
<svg width="100%" height="360" style="background-color: rgb(0, 249, 253);margin-top: 50px;">
<rect y1="0" y2="100" x="0" width="100" height="100"></rect>
<text x="100" y="0" dominant-baseline="hanging">2022</text>
</svg>
Any idea why this is happening?
According to the SVG specification, a dominant baseline of hanging is only meaningful for Indic scripts like Devanagari. If you want the top edge of the text box to align with a particular Y coordinate, then use text-before-edge instead:
<svg width="300" height="55" viewBox="0 0 300 55">
<rect x="20" y="5" width="30" height="30" fill="#f00"/>
<text x="50" y="5" dominant-baseline="hanging">8888</text>
<text x="35" y="50" text-anchor="middle">hanging</text>
<rect x="220" y="5" width="30" height="30" fill="#f00"/>
<text x="250" y="5" dominant-baseline="text-before-edge">8888</text>
<text x="235" y="50" text-anchor="middle">text-before-edge</text>
</svg>

svg mask and bounding box

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

Resources