I have done a table in SVG, and I want to fill it with data dynamically. That means that I don't know how much space the text takes, and I want to clip or hide the overlapping text. How can I do that in SVG?
My HTML document with SVG looks like:
<!DOCTYPE html>
<html>
<body>
<svg>
<text x="100" y="100">Orange</text> <text x="160" y="100">12</text>
<text x="100" 开发者_如何学Goy="115">Pear</text> <text x="160" y="115">7</text>
<text x="100" y="130">Banana</text> <text x="160" y="130">9</text>
<text x="100" y="145">Pomegranate</text><text x="160" y="145">2</text>
<line x1="157" y1="85" x2="157" y2="155" style="stroke:rgb(100,100,100)"/>
</svg>
</body>
</html>
And this will render to:
Is there any way I can clip the text i my SVG-"table"?
Implemented solution from Erik's answer:
<!DOCTYPE html>
<html>
<body>
<svg>
<text x="10" y="20" clip-path="url(#clip1)">Orange</text>
<text x="10" y="35" clip-path="url(#clip1)">Pear</text>
<text x="10" y="50" clip-path="url(#clip1)">Banana</text>
<text x="10" y="65" clip-path="url(#clip1)">Pomegranate</text>
<text x="70" y="20">12</text>
<text x="70" y="35">7</text>
<text x="70" y="50">9</text>
<text x="70" y="65">2</text>
<line x1="67" y1="5" x2="67" y2="75" style="stroke:rgb(100,100,100)"/>
<clipPath id="clip1">
<rect x="5" y="5" width="57" height="90"/>
</clipPath>
</svg>
</body>
</html>
You can use clip-path to clip to whatever shape you want, see e.g masking-path-01 from the svg testsuite.
Relevant parts, defining the clip path:
<clipPath id="clip1">
<rect x="200" y="10" width="60" height="100"/>
... you can have any shapes you want here ...
</clipPath>
and then apply the clip path like this:
<g clip-path="url(#clip1)">
... your text elements here ...
</g>
If for some reason you don't want to use clipping, you can also use a nested SVG tag:
<svg>
<svg x="10" y="10" width="10" height="10">
<text x="0" y="0">Your text</text>
</svg>
</svg>
This way, your text will be cut off when it's outside the nested SVG viewport. Note that the x
and y
of the text
tag refer to the coordinate system of the nested SVG, and correspond to 10 in the coordinate system of the outer SVG.
As Marcin said in point (2) of his answer (unfortunately downvoted but actually this is a good point) an alternative way to achieve the effect is to overpaint the part not wanted with a white rectangle.
<!DOCTYPE html>
<html>
<body>
<svg>
<text x="100" y="100">Orange</text>
<text x="100" y="115">Pear</text>
<text x="100" y="130">Banana</text>
<text x="100" y="145">Pomegranate</text>
<!-- Overpaint the overflowing text -->
<rect x="155" y="85" width="100" height="100" fill="white" />
<line x1="157" y1="85" x2="157" y2="155" style="stroke:rgb(100,100,100)"/>
<text x="160" y="100">12</text>
<text x="160" y="115">7</text>
<text x="160" y="130">9</text>
<text x="160" y="145">2</text>
</svg>
</body>
</html>
Reference to the SVG specification: SVG 2.0 Rendering Order
(1) There is no reason to use SVG for tables. Use HTML tables.
(2) By "clipping" I understand you to mean that the excess text will be obscured. SVG uses a "painter's model" whereby elements specified later in the document are drawn above elements specified earlier. This will allow you to clip regions.
(3) If you really needed to do this in an SVG document you could use a foreign object, and embed HTML.
If you don't want to use a clip-path
, which can be a pain if each element has a different size, then you can also use nested <svg>
elements for clipping. Just make sure the svg
elements have the CSS style overflow:hidden
.
<!DOCTYPE html>
<html>
<body>
<svg>
<svg width="57" height="15" x="10" y="5"><text y="15">Orange</text></svg>
<svg width="57" height="15" x="10" y="20"><text y="15">Pear</text></svg>
<svg width="57" height="15" x="10" y="35"><text y="15">Banana</text></svg>
<svg width="57" height="15" x="10" y="50"><text y="15">Pomegranate</text></svg>
<text x="70" y="20">12</text>
<text x="70" y="35">7</text>
<text x="70" y="50">9</text>
<text x="70" y="65">2</text>
<line x1="67" y1="5" x2="67" y2="75" style="stroke:rgb(100,100,100)"/>
</svg>
</body>
</html>
精彩评论