Jimmy
Jimmy

Reputation: 12487

Javascript SVG resize work on chrome but not safari

I've got some code which is designed to resize the text on an SVG so that it fits within a certain size.

It seems to work fine on chrome but not in any other browser (I tried IE11 and Safari).

This is the code

<html>
  <body>
  <style>
@import url('https://fonts.googleapis.com/css?family=Sonsie+One');
text {
  font-family: "Sonsie One";
}
svg {
  background: #43C6AC;
}
</style>
<svg version="1.2" viewBox="0 0 600 400" width="600" height="400" xmlns="http://www.w3.org/2000/svg">
  <text id="t1" style="fill: white;" x="50%" y="50%" text-anchor="middle">Test</text>
</svg>
<script>
function resize() { 
    var width = 350,
      height = 80;
    var textNode = document.getElementById("t1");
    for (var k = 1; k < 60; k++) {
      textNode.setAttribute("font-size", k)
      var bb = textNode.getBBox()
      if (bb.width > width || bb.height > height)
        break;
    }
}
window.onload = resize;      
</script>
</body>
</html>

This is it running on a url: http://hiven.com/momo.html

Can anyone please tell me where I am going wrong? In chrome it resizes the text to 350px but in others it doesn't.

Upvotes: 1

Views: 303

Answers (1)

defghi1977
defghi1977

Reputation: 5349

I found this problem is caused by timing of font loading. (I tested on Epiphany WEB which has WebKit rendering engine as Safari.)

Since window.onload is called before completion of font loading, resize method works under fallback font style, thus the text size gotten by bbox was incorrect.

So this problem is solved by waiting completion of font loading. But apis of font loading as document.fonts.onloadingend or document.fonts.load seem to be not supported on WebKit (or have no effect on this case).

Thus I made the waiting system by canvas element like this (but I think this is not best.)

<html>
  <body>
        <style>
    @import url('https://fonts.googleapis.com/css?family=Sonsie+One');
    text {
        font-family: "Sonsie One";
    }
    svg {
        background: #43C6AC;
    }
        </style>
        <svg viewBox="0 0 600 400" width="600" height="400">
            <text id="t1" style="fill: white;" x="50%" y="50%" 
            text-anchor="middle">Test some long text here</text>
        </svg>
        <script>
function resize() {
    var width = 350,
      height = 80;
    var textNode = document.getElementById("t1");
    for (var k = 1; k < 60; k++) {
      textNode.setAttribute("font-size", k)
      var bb = textNode.getBBox()
      if (bb.width > width || bb.height > height)
        break;
    }
}

//window.onload = resize;
//waiting font loading
{
    var cnt = 0;
    function tryResize(){
        if(!ready() && cnt < 30){
            setTimeout(tryResize, 100);
            cnt++;
        }else{
            resize();
        }
    }
    //check the state of font loading
    var c1 = document.createElement("canvas");
    var c2 = c1.cloneNode(false);
    var ctx1 = c1.getContext("2d");
    var ctx2 = c2.getContext("2d");
    //set target font and fallback font 
    ctx1.font = "normal 30px 'Sonsie One', serif";
    ctx2.font = "normal 30px serif";
    var text = "this is test text.";  
    function ready(){
        //compare text length.
        //when the target font loading is complted, 
        //the legth of text will be changed
        return ctx1.measureText(text).width != ctx2.measureText(text).width;
    }
    //start waiting
    tryResize();
}
        </script>
    </body>
</html>

DEMO:http://jsdo.it/defghi1977/ueFO

Upvotes: 1

Related Questions