在给定viewBox维度和文本样式的情况下,如何计算将svg文本放在viewBox中的翻译?

时间:2016-06-16 14:31:42

标签: javascript jquery html svg

我试图了解<text>在svg中的定位。

假设您有<svg viewBox="..."><text>...</text></svg>,其中viewBox的大小正确,以适合给定(已知)字体,字体粗细和字体大小的文本。如果不提供<text> x="..." y="..."翻译,则无法定位&#34;正确&#34;在viewBox中:它会太高,而且会在右边。

我可以计算那些xy翻译值吗?如果翻译不依赖于字体的特征,或者分析绘制的<text>(如果它确实依赖于字体&#39;},则可能无法分析绘制的<text>。的特点。

这是一个例子(也是一个jsfiddle:https://jsfiddle.net/enry/Lnzxx0jx/)。这是从Sketch导出的 - 这就是为什么我无法访问进行x和y翻译的计算的原因。 <svg>是红色轮廓的东西。需要注意的是,这些特定的x和y转换值是需要,以便将文本放置在viewBox中,以便隐藏<svg>的溢出时整个<text>可见。

&#13;
&#13;
text {
    fill: #000;
    fill-rule: evenodd;
    font-weight: 700;
    font-family: Helvetica-Bold, Helvetica;
    font-size: 36px
}
/* just for demo purposes */
html {
    padding: 20px;
    background: #ccc
}
svg {
    outline: 1px solid red;
    background: #fff;
    overflow: hidden /* in case you want to play around with the translation */
}
&#13;
translated
<svg viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
    <text x="-2" y="26"><!-- << the question:
                                if these values weren't provided,
                                how would you calculate them? -->
        my sample text
    </text>
</svg>

not translated
<svg viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
    <text><!--                  fwiw, the getBBox of the text without translation is
                                somewhere around -33 - -34, depending on the svg's actual size-->
        my sample text
    </text>
</svg>
&#13;
&#13;
&#13;

那么为什么翻译值为x =&#34; -2&#34;和y =&#34; 26&#34;?我尝试了各种百分比的viewBox维度;各种百分比的字体大小;和viewBox与font-size相关的分数......但无法弄明白。

它们可能依赖于kerningleading - 字母周围的空间。在那种情况下,我想我们在绘制之前不能知道必要的翻译,此时可能用js / jquery测量字符周围的空间?如果是这样,将如何做(我没有使用脚本分析打印字符的经验)。 Fwiw(这是在讨论中提到的),未翻译文本的getBBox是x:0,y: - [非常接近34,取决于svg的实际大小] - 所以,y非常差不多 - (viewBox y)。因为getBBox不需要svg来拥有一个viewBox,所以这可以用来动态地确定viewBox ...但它似乎没有帮助进行翻译计算。

或者它是基于viewBox的一些计算?在我的实验中,翻译值 依赖于字体和字体大小...但是viewBox也是如此,所以也许我们只需要viewBox维度来计算翻译。

我猜: 对于x翻译来说,字距调整很有意义 - 我可以想象svg会被领先的空格绊倒,这就可以解释为什么它必须向左拉一点。 y转换的一部分是将基线向下移动到viewBox的底部,但考虑到必须转换x的事实,我希望y是基线加上一些调整 ...并且要求计算两者调整(可能是前导?)文本高度(上限高度+可能是上升高度+可能是下降高度 - ["typeface anatomy" illustration])

1 个答案:

答案 0 :(得分:2)

您的问题令人困惑,因为我们希望您能够更好地了解(比互联网上的随机陌生人)答案是什么。

  

我真正的问题是x =&#34; -2&#34;和y =&#34; 25&#34;来自。

这就像问为什么书是蓝色的,或者为什么它在书架的左端。它就在那里因为你或者设计SVG的人把它放在那里。

如果您已经不熟悉,SVG不是HTML。事物不会像HTML一样自动定位。您必须在SVG文档中指定元素的位置和大小。

如果您想知道文本的位置,请去询问设计师。

我的猜测

..如果您使用给定文本并将其大小设置为36px,请将其字体设置为&#34; Proxima Nova&#34;,然后将其定位以使其位于页面的左上角,然后:

  1. 右下角位于(241,33)
  2. 文本基线开始位置为(-2,25)
  3. 从而解释生成的文本x,y coords和viewBox值。

    但我没有这种字体,所以我无法确定。

    <强>更新

    如果您需要在浏览器中重新定位文本,可以在某个初始位置和字体大小处添加文本。然后在文本元素上调用getBBox()。这将为您提供相对于初始文本位置的文本范围。基于此,您可以计算最终位置和大小。您还可以修改viewBox,以便在需要时正确缩放文本。

    &#13;
    &#13;
    // Find the text element
    var mytext = document.getElementById("mytext");
    
    // Get it's bounding box
    var bbox = mytext.getBBox();
    
    // Reposition text using the values from its bounding box
    mytext.setAttribute("x", -bbox.x);
    mytext.setAttribute("y", -bbox.y);
    // Top left of text should now be at top-left of SVG (0,0)
    
    // Now update the SVG viewBox so that it is fitted to the text
    document.getElementById("mysvg").setAttribute("viewBox", "0 0 "+bbox.width+" "+bbox.height);
    
    // Note that the bbox of the text is not tightly fitted to the text.  It includes the em boxes 
    &#13;
    text {
        fill: #000;
        fill-rule: evenodd;
        font-weight: 700;
        font-family: Helvetica-Bold, Helvetica;
        font-size: 36px
    }
    /* just for demo purposes */
    html {
        padding: 20px;
        background: #ccc
    }
    svg {
        outline: 1px solid red;
        background: #fff;
        overflow: hidden /* in case you want to play around with the translation */
    }
    &#13;
    <svg id="mysvg" viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
        <text id="mytext" x="0" y="0">my sample text</text>
    </svg>
    &#13;
    &#13;
    &#13;

    在上面的例子中,我们正在移动文本位置。但我们并不是真的需要。仅设置viewBox将具有相同的结果。

    &#13;
    &#13;
    // Find the text element
    var mytext = document.getElementById("mytext");
    
    // Get it's bounding box
    var bbox = mytext.getBBox();
    
    // Now update the SVG viewBox so that it is fitted to the text
    document.getElementById("mysvg").setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height].join(' '));
    &#13;
    text {
        fill: #000;
        fill-rule: evenodd;
        font-weight: 700;
        font-family: Helvetica-Bold, Helvetica;
        font-size: 36px
    }
    /* just for demo purposes */
    html {
        padding: 20px;
        background: #ccc
    }
    svg {
        outline: 1px solid red;
        background: #fff;
        overflow: hidden /* in case you want to play around with the translation */
    }
    &#13;
    <svg id="mysvg" viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
        <text id="mytext" x="0" y="0">my sample text</text>
    </svg>
    &#13;
    &#13;
    &#13;