0

edit - originally thought this was just an SVG problem but seems to apply more broadly.

I'm trying to draw some text in SVG and then put a rectangle around it with padding on the right side in SnapSVG. This works just fine with any web safe font. When I import a font from google, however, .getBBox() returns the wrong width. SO's web snippets don't seem to replicate the problem so I've put in the code here but to see the actual problem you need to go to the codepen below.

var testsvg = Snap('#test')
testsvg.rect(0,0,400,400).attr({})
var pretext=testsvg.text(100,50,'I am the very model of').attr({fill:'white','font-family':"Asap"})
var text=testsvg.text(100,100,'I am the very model of').attr({fill:'white','font-family':"Asap"})
console.log(text.getBBox().width)
var boundrect=testsvg.rect(100,100-text.getBBox().height,text.getBBox().width+10,text.getBBox().height).attr({stroke:'white',fill:'none'})
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<style>
 @import url('https://fonts.googleapis.com/css?family=Asap');
</style>

<svg id='test' height='400' width='400'></svg>

Here's the codepen: https://codepen.io/austinclemens/pen/WKZayE

You'll notice that the rectangle is supposed to have a width of the text width + 10 but it ends up not fully enclosing the box. If you change the text to say Arial, it will work immediately. In addition, if you change the text to Arial and then back to Asap, suddenly Asap will work. I experience the bug in Safari, Chrome, and Firefox. Adding window.onload() before executing the JS doesn't seem to help nor does using an arbitrary wait.

So I suspect this has something to do with fonts loading. I thought perhaps I could fix it by 'initializing' the font so to speak by doing a different text object first but that doesn't help. I could use an HTML solution but in my actual application that would be pretty cumbersome so I'd like to get it working with only Snap if possible. I don't actually think this is a snap problem either. Looking at snap's getbbox function, it uses this.node.getClientRects() for text, which returns the wrong width here.

AustinC
  • 826
  • 1
  • 8
  • 23
  • Ugh, I added an html test to the codepen and it doesn't work either. Using setTimeout to wait to get the length until after the element is drawn works. But this seems super clumsy. Is there an accepted solution to this problem? – AustinC Jul 27 '18 at 21:04
  • 1
    This might be helpful: https://stackoverflow.com/questions/5680013/how-to-be-notified-once-a-web-font-has-loaded – Asons Jul 27 '18 at 21:15

1 Answers1

0

Per LGSon's recommended post, I used fontfaceobserver to fix this problem by loading fonts with promises: https://github.com/bramstein/fontfaceobserver

AustinC
  • 826
  • 1
  • 8
  • 23