I have a SVG group element such as this:
<g transform="translate(290 110)">
<rect x="0" y="0" rx="4" ry="4" width="68" height="68" style="fill:none;stroke:black;stroke-width:1;" />
</g>
I would like to add some text that is aligned with the inside bottom-left border of the rect. Sort of like the left and bottom CSS attributes in HTML.
How do I accomplish this?
[edit]
One problem with trying to calculate the offsets myself is that I can't mix and match px and em measurements in the same calculation. For instance, the container is 68x68px, but I want to offset the text 1em from the bottom. Also, the distance from one tspan to the next should be based on something other than pixels.
To align multuiple rows of text, just use <tspan> and the dy attribute.
<svg width="400" height="400">
<g transform="translate(290 110)">
<rect x="0" y="0" rx="4" ry="4" width="68" height="68" style="fill:none;stroke:black;stroke-width:1;" />
<text y="68">
<tspan>First line</tspan>
<tspan x="0" dy="-1em">Second line</tspan>
<tspan x="0" dy="-1em">Third line</tspan>
</text>
</g>
</svg>
Related
I'm trying to create a filter for only the stroke of path in SVG, but the feImage keeps getting clipped to what I assume is that bounding box (see green rectangle below in code as bounding box). I've tried setting the filter's x/y and width/height to all sorts of positions/sizes, as seems to be the prevailing advice, but nothing works. x/y just offset the feImage and width/height of greater than 100% has no effect.
I won't know in advance if the stroke or fill is solid or something else (like linearGradient.
The below demonstrates what I'm looking to do - just get the stroke of a shape (regardless of size or fill) and apply a filter to it for all modern browsers.
Notes: FF doesn't even display the left-hand feImage. Chrome clips the left and top. Edge clips all 4 sides.
<html>
<body>
<svg width="960" height="540" >
<rect width="960" height="540" stroke="#385D8A" fill="white" stroke-width="3"/>
<svg name="BoundingBox1" class="rect" x="100" y="100" overflow="visible" fill="none" stroke="#00ff00" stroke-width="1">
<path d="M0,0L121.68,0L121.68,121.68L0,121.68Z" />
</svg>
<!-- BELOW IS MODIFIED "SPEECH" SHAPE. NEED A FILTER ON THE STROKE ONLY. -->
<svg name="Speech-strokeonly" x="100" y="100" overflow="visible" fill="blue" stroke="orange" stroke-width="12" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="M35.541,137.084L30.985,113.988A60.926,60.926 0 1 1 53.043,121.34Z" id="strokeOnly" fill="none"/>
<filter id="effs0sp9" color-interpolation-filters="sRGB" x="0" y="0">
<feImage xlink:href="#strokeOnly" />
</filter>
</defs>
<path d="M35.541,137.084L30.985,113.988A60.926,60.926 0 1 1 53.043,121.34Z" id="effs0sp9" filter="url(#effs0sp9)" overflow="visible" />
<text y="160" stroke="black" stroke-width="0.2">this is the one that has undesirable clipping of</text>
<text y="178" stroke="black" stroke-width="0.2">of stroke in Chrome/Edge. Doesn't appear at all in FF</text>
</svg>
<!-- BELOW IS ORIGINAL WITH BOTH FILL AND STROKE -->
<svg name="BoundingBox2" x="400" y="100" overflow="visible" fill="none" stroke="green" stroke-width="1">
<path d="M0,0L121.68,0L121.68,121.68L0,121.68Z" />
</svg>
<svg name="Speech-original" x="400" y="100" overflow="visible" fill="blue" stroke="orange" stroke-width="12">
<path d="M35.541,137.084L30.985,113.988A60.926,60.926 0 1 1 53.043,121.34Z" id="effs0sp9" />
<text y="-22" stroke="black" stroke-width="0.2">this is the original one</text>
<text y="-6" stroke="black" stroke-width="0.2">that I just want the stroke as feImage from</text>
</svg>
</svg>
</body>
</html>
Is there a way to grab the whole stroke of a shape only and use in a filter?
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>
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>
The following code infact wraps text on a rectangle.
But when I want to drag the rectangle, i also want the text to be dragged simultaneously,i.e, the text must be bound to the rectangle on drag and drop.
Please help me.
<svg xmlns="http://www.w3.org/2000/svg">
<g id='Propositions'>
<rect id='Proposition1' x='50' y='50' width='100' height='30' style='fill:#8FBC8F; '/>
<text x="55" y="72" font-family="Verdana" font-size="14" fill="black" > Proposition1</text>
</g>
</svg>
Thanks in advance..
Drag the <g> element(parentNode), rather than the rect. This, then will include the text in the drag/drop event.
e.g.
<g id='Propositions'>
<rect id='Proposition1' onmousemove=dragMe(evt) x='50' y='50' width='100' height='30' style='fill:#8FBC8F; '/>
<text pointer-events=all x="55" y="72" font-family="Verdana" font-size="14" fill="black" > Proposition1</text>
</g>
function dragMe(evt)
{
myG=evt.target.parentNode
myG.setAttribute("transform", "translate("+transX+" "+transY+")")
}
I need to get text with desired height and width.
I tried to find something in documentation of svg but found only font-size and also I tried to use scale in such manner:
<text xmlns="http://www.w3.org/2000/svg" id="10996080909940" name="-1"
x="1782.9351809218" y="-751.796133712862" width="1" height="1" style="font:Arial;text-
anchor:start;stroke:#000000" transform="rotate(0) scale(2 2)"> SOME TEXT </text>
But I get too big size of text and in place not where I need.
If you mean you want the text to exactly fill an arbitrary width and height, then there isn't really an easy way to do it in SVG. You can't specifiy a width and height on the <text> element. At least not in the current SVG spec (1.1).
However there are several ways to achieve this effect with a bit of trickery.
One way is by using a transform, as you suggested:
<svg>
<text font-size="10px" font-family="Verdana" transform="translate(99,400) scale(3.5,13.7)">SQUASHED TEXT</text>
<rect x="100" y="300" width="300" height="100" fill="none" stroke="red" />
</svg>
A second way is by using an inner <svg> element and setting the viewBox to match the bounds of the text. You then set preserveAspectRatio="none".
<svg>
<svg x="100" y="100" width="300" height="100" viewBox="0.2 -7.3 86 7.3" preserveAspectRatio="none" overflow="visible">
<text font-size="10px" font-family="Verdana">SQUASHED TEXT</text>
</svg>
<rect x="100" y="100" width="300" height="100" fill="none" stroke="red" />
</svg>
This way is more verbose, but it has the advantage that once you have found the correct viewBox for a piece of text, you can make it fit any sized rectangle very easily. Just set the x,y,width and height of the inner <svg> to the size of the rectangle.
Demo here: http://jsfiddle.net/ZRgEF/3/