I am trying to figure out how to use SVG.js to draw text. In my attempt below, the text is being created and drawn, but only a few dots show up. This must be part of the text being drawn, but it is being clipped. I am not sure why this clipping is happening or how to fix it.
My end goal is to create an SVG with text fitted inside some geometry. To do this, I need to measure the text first so I can compute the geometry dimensions. Therefore, it is important to me to create the SVG object before adding the SVG to a DOM element.
For the code below, what do I need to do so the text show up correctly?
const draw = SVG().size(300, 300);
const text = draw.text("000000000");
text.attr({
fill: "red",
stroke: "green",
"font-family": "Roboto",
"font-size": 10
});
const bbox = draw.bbox()
console.log( bbox );
draw.addTo("#rectID");
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/[email protected]/dist/svg.min.js"></script>
<div id="rectID">
</div>
As explained by Fuzzyma:
the bbox is calculated by creating a temporarily appended DOM element.
In fact this approach should work flawlessly without any layout shifts.
Your main problem is the off canvas position of the <text>
element.
Here's an example generating a horizontally and vertically centered <text>
element with a <rect>
in the background.
The SVG's markup is returned via svg()
method.
const draw = SVG().size(300, 300);
// draw background rect
const rect = draw.rect();
const text = draw.text("000000000");
text.attr({
fill: "red",
"font-family": "Roboto",
"font-size": 50,
x: "50%",
y: "50%",
"text-anchor": "middle",
"dominant-baseline" : 'middle'
});
// get bounding box
const bbox = draw.bbox();
// adjust rect dimensions according to bbox
rect.attr({
x: bbox.x,
y: bbox.y,
width: bbox.width,
height: bbox.height,
fill: "#ccc",
stroke: "green"
});
// get markup
let markup = draw.svg()
output.value = markup;
function render(){
document.body.insertAdjacentHTML('beforeend', markup)
}
svg{
border:1px solid #ccc;
}
textarea{
width:100%;
min-height:10em
}
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/[email protected]/dist/svg.min.js"></script>
<h3>SVG markup</h3>
<textarea id="output"></textarea>
<p><button onclick="render()">Render SVG</button></p>
As you can see we can also retrieve the SVG markup without rendering the element - albeit the bbox calculation requires some temporary invisible rendering.