I was trying to put a title for a img of SVG.
The title is at the bottom of the pic.
The code goes like:
<svg>
<image>
</svg>
How to realize this without using inner ?
And I also wanna make it based on D3.js , if possible.
Thanks.
In SVG elements, you don't use a title attribute. You have to use a <title> element, which you put inside the element to which it applies.
<svg>
<image xlink:href="http://lorempixel.com/300/150/" width="300" height="150">
<title>foobar</title>
</image>
</svg>
You could simply put a piece of text below the image. Put the text y position = image height + a little padding. Or you could put the y position a bit less than the image height and it would land on top of the image.
<?xml version="1.0" encoding="utf-8"?>
<!-- from this website http://tutorials.jenkov.com/svg/svg-and-css.html -->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<image x="0" y="0" height="100" width="100" id="HVACEast" preserveAspectRatio="none" xlink:href="https://some.site.com/image.png" opacity="0.4" style="pointer-events: none"/>
<text stroke-width=".05" fill="#66CCB2" x="5" y="105" font-family="serif" font-size="5pt">IMAGE TITLE</text>
</svg>
Or use tspan for the text.
<text>
<tspan x="5" y="105" font-size="5pt" fill="yellow">Image</tspan>
<tspan x="5" y="108" font-size="5pt" stroke="blue">Title</tspan>
</text>
Related
There are similar questions like this, but none are identical.
The goal is to scale text as its enclosing rectangle or SVG element scales.
In the example below, the enclosing SVG element is 200x300.
The goal is for the whole element to preserve proportionality, including text.
If you scale by 0.5 to 100x150, the text should scale accordingly.
However, changing the size to 100x150 scales the SVG element correctly, but the text remains the same size and no longer retains the same proportions to the enclosing container.
Code pen: https://codepen.io/anon/pen/BvLZKv?page=1&
<svg width="200" height="300">
<g>
<rect x="0" y="0" width="100%" height="100%" fill="red"></rect>
<text x="50%" y="50%" font-family="Verdana" font-size="20" fill="blue" dominant-baseline="middle" text-anchor="middle">Hello</text>
</g>
</svg>
You can create the base svg and scale that entire svg with a scale value, then the text also will be scaled.
Here is a demo in which I scaled the svg to .5, the entire svg with the text is scaled to half.
svg {
transform: scale(.5);
transform-origin: 0% 0%;
}
<svg width="200" height="300">
<g>
<rect x="0" y="0" width="100%" height="100%" fill="red"></rect>
<text x="50%" y="50%" font-family="Verdana" font-size="82" fill="blue" dominant-baseline="middle" text-anchor="middle">Hello</text>
</g>
</svg>
I have an <image> inside of an <svg> that is not displaying. I have checked the SVG spec and several SVG demos. This code should work, but the image does not appear. Any ideas?
<svg width="415" height="240">
<g transform="translate(115, 0)">
<image href="img/test.png" width="143" height="15" x="0" y="0"></image>
</g>
</svg>
The image href URL is correct :)
You are missing xlink
<image xlink:href="img/test.png" width="143" height="15" x="0" y="0"></image>
Is there a way - preferably without using JavaScript - to put some HTML contents into an SVG shape using foreignObject, such that the SVG shape will auto-resize (or scale) to fit its contents?
I.e. something very vaguely like this pseudocode example, but valid, and functional in the way I've described:
<?xml version="1.0" standalone="yes"?>
<svg xmlns = "http://www.w3.org/2000/svg">
<rect x="10" y="10" width="SCALE_TO_FIT_CONTENTS" height="SCALE_TO_FIT_CONTENTS" fill="gray">
<foreignobject width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>Some HTML text</div>
</body>
</foreignobject>
</rect>
</svg>
without using javascript, there is no possible way you could do that. In fact, the SVG shapes cannot be used as containers. But, I hope this is what you're asking for:
<script type="text/javascript">
function myFun(){
var w = document.getElementById("myDiv").scrollWidth;
document.getElementById("myRect").setAttribute("width",w);
}
</script>
<svg xmlns = "http://www.w3.org/2000/svg" onload="myFun()">
<rect id="myRect" x="10" y="10" width="0" height="100" fill="red"></rect>
<foreignObject x="10" y="10" position="absolute" width="100%" height="100%">
<div id="myDiv" style="display: inline-block;">Some HTML text that resizes its SVG container</div>
</foreignObject>
</svg>
A nice trick would be to wrap everything in a <g> element and then measure that element using getBBox() and then the height of the inner content is known, and could be used to modify the parent SVG element's height.
var svg = document.querySelector('svg');
var bbox = svg.firstElementChild.getBBox();
svg.setAttribute("height", bbox.height + "px");
<svg>
<g>
<rect x="10" y="10" width="100" height="200px" fill="red"></rect>
<foreignObject x="10" y="500" position="absolute" width="100%" height="100%">
<div id="myDiv" style="display: inline-block;">Some HTML text that resizes its SVG container</div>
</foreignObject>
<text dy='500'>aaaaaaaaa</text>
</g>
</svg>
I'm able to create an SVG Image which contains a filled SVG path, as already mentioned in this question: Fill SVG path element with a background-image
The SVG looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1">
<g transform="translate(0, 0) rotate(0)" opacity="1">
<defs>
<pattern id="img_patrickComp_patrick_cv1_Graphic3" height="313" width="468" patternTransform="translate(0, 0) scale(1, 1) rotate(0)" patternUnits="userSpaceOnUse">
<image x="0" y="0" opacity="1" height="313" width="468" xlink:href="http://www.bittbox.com/wp-content/uploads/2008/04/free_hires_wood_texture_5.jpg" />
</pattern>
</defs>
<path fill="url(#img_patrickComp_patrick_cv1_Graphic3)" stroke="Blue" d="M 86,100L 298,394L 289,710L 100,610L 100,400L 46,400 z" />
</g>
</svg>
(Link to the SVG: http://jsfiddle.net/2UFtV/)
Is it possible to create the same textured SVG without knowing the width and height of the image?
If you want to preserve the raster image at it's native dimensions you need to know the dimensions yes.
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" y="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>