2

I want to create a SVG element, which include a list of node, each node is a rectangle with a text inside:

<svg class="chart" width="420" height="150" aria-labelledby="title" role="img">
            <ng-container *ngFor="let item of listNode">
                <g viewBox="0 0 56 18">
                    <rect [attr.width]="item.w" [attr.height]="2*item.h"  fill="white"></rect>

                    <text [attr.x]="item.x" [attr.y]="item.y" text-anchor="middle" font-family="Meiryo" font-size="item.h"
                        fill="black">{{item.label}}</text>
                </g>
            </ng-container>
        </svg>

But I want to put the text is in center of the rectangle (both vertically and horizontally). To do this, I think I need to measure the width of text before creating the SVG element. I tried to use the below function to measure text size:

getTextWidth(text, fontSize, fontFace) {
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    context.font = fontSize + 'px ' + fontFace;
    return context.measureText(text).width;
  }

But the result is not correct. So, Is there any way to measure size of SVG text element before creating the real element (like my getTextWidth function), or is there any other way to create rectangle with text is exactly in center.

Waveter
  • 890
  • 10
  • 22
  • Possible duplicate of [Measuring dimensions of svg elements in Angular](https://stackoverflow.com/questions/51703422/measuring-dimensions-of-svg-elements-in-angular) Measuring the size in canvas is the equivalent of using `.getBoundingClientRect()` - it's the wrong coordinate system. – ccprog Dec 13 '18 at 17:36
  • Btw, the `` element has no `viewBox` attribute - use a `` element instead. – ccprog Dec 13 '18 at 17:41
  • you can to change the size of the rectangle after measuring the text – enxaneta Dec 13 '18 at 18:28
  • 1
    Is [this](https://stackoverflow.com/questions/15500894/background-color-of-text-in-svg/31013492#31013492) not suitable. No measuring required. – Robert Longson Dec 13 '18 at 20:27

1 Answers1

2

There are many ways to measure the text width and height but if you have the text itself and its font properties, you already have it.

1) Let's suppose you don't want to do the math, you can use HTMLElement properties.

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
</head>
<body>
  <script>
    const span = document.createElement('span')
    document.body.append(span)
    span.style = 'font-family: Arial; font-size: 14px'
    span.innerHTML = 'TEXT' 
    document.body.textContent = 
      `width: ${span.offsetWidth} height: ${span.offsetHeight}`
    span.remove()
  </script>
</body>
</html>

Note: don't forget to append your element.

2) Use those dimensions to set your rect dimensions (add extra if you want padding) and set your text in the middle like so:

<text 
    style="font-family: Arial; font-size: 14px" 
    x="50%" 
    y="50%" 
    dominant-baseline="middle" 
    text-anchor="middle">TEXT</text>

Note: use always the same style in your text.

Hope this help :)

gengns
  • 1,573
  • 14
  • 23