【问题标题】:Getting the size of text without using the boundingBox function in Raphael javascript library在 Raphael javascript 库中不使用 boundingBox 函数获取文本大小
【发布时间】:2013-01-28 02:03:41
【问题描述】:

我正在尝试使用 Rahpael 库在 javascript 中创建一些带有文本的按钮。我想在绘制之前知道样式文本的大小以避免这种情况,以便我可以创建适当的背景(按钮)。另外我想避免在画布/纸张之外绘制文本(文本的位置是它的中心位置)。

我可以使用 Raphaels getBBox() 方法,但我必须首先创建(绘制)文本才能做到这一点。所以我绘制文本以获得能够在正确位置绘制它的大小。这很丑陋。所以我正在寻找一些通用方法来估计给定字体、字体大小、系列的样式文本的度量......

使用 HTML5 画布http://www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/ 可以做到这一点,但拉斐尔不使用画布。是否有可能使用 Raphael 或纯 Javascript 获取文本指标?

【问题讨论】:

    标签: javascript text size raphael metrics


    【解决方案1】:

    我知道这看起来很草率,但你应该可以毫无问题地绘制文本、测量文本、然后绘制按钮和移动标签。为了安全起见,只需将其从屏幕上绘制出来:

    var paper = Raphael(0, 0, 500, 500);
    
    var text = paper.text(-100, -100, "My name is Chris");
    
    //outputs 80 12
    console.log(text.getBBox().width, text.getBBox().height);
    

    但是,如果这真的冒犯了您的情感——我会理解的! -- 您可以轻松地生成一个对象来记住给定字体的每个字符的宽度:

    var paper = Raphael(0, 0, 500, 500),
        alphabet = "abcdefghijklmnopqrstuvwxyz";
        font = "Arial",
        charLengths = {},
        ascii_lower_bound = 32,
        ascii_upper_bound = 126;
    
    document.getElementById("widths").style.fontFamily = font;
    
    for (var c = ascii_lower_bound; c <= ascii_upper_bound; c += 1) {
        var letter = String.fromCharCode(c);    
        var L = paper.text(-50, -50, letter).attr("font-family", font);
        charLengths[letter] = L.getBBox().width;
    }
    
    //output
    
    for (var key in charLengths) if (charLengths.hasOwnProperty(key)) {
        var row = document.createElement("tr");
        row.innerHTML = "<td>" + key + "</td><td>" + charLengths[key] + "</td>";    
        document.getElementById("widths").appendChild(row);    
    }
    

    【讨论】:

    • 非常感谢您的回答。 Cufonized 字体没有问题,因为我需要文本表现得像普通文本,可选择并支持复制。此外,我还没有考虑的想法是文本换行。您的第二个建议是用一个对象(地图)保存用特定字体和字体大小打印的字母宽度,对此非常有用。有一个问题,如果没有比使用 Raphael 文本对象更好的解决方案,比如结合 Raphael 和普通 div ...
    • 是的,我几乎总是在 SVG/VML 文本框上使用常规 div,特别是用于包装(以及对 CSS 的完全访问)。如果它对你有用,你能接受答案吗?需要确认我的自我价值;)
    • user1991697 - 您绝对应该确认@ChrisWilson 的回答对您有用。克里斯,我会投入我的 0.02 美元。
    • 您好,我当然确认答案 - 无论如何,再次非常感谢。但是,我担心,计算字符串中所有字符的宽度总和并不能得出准确的测量结果,例如,由于某些“印刷”原因,字母“ae”经常被打印得很近。我试图在咖啡脚本中实现假定的解决方案以进行文本换行,但结果好坏参半。但是我假设我的代码中可能存在错误。如果有人想检查它,我在这里发布了代码:pastebin.com/C3u1m36a
    • 谢谢,凯文。而用户\d+,您可能应该采用我们都建议的视野外解决方案。
    【解决方案2】:

    有几种方法可以切开这只猫。很容易想到两个明显的。

    视野外标尺技术

    这是最简单的。只需在画布的 viewBox 之外创建一个文本元素,用您的字体信息和文本填充它,然后测量它。

    // set it up -- put the variable somewhere globally or contextually accessible, as necessary
    var textRuler = paper.text( -10000, -10000, '' ).attr( { fill: 'none', stroke: 'none' } );
    
    function getTextWidth( text, fontFamily, fontSize )
    {
        textResult.attr( { text: text, 'font-family': fontFamily, 'font-size': fontSize } );
        var bbox = textResult.getBBox();
        return bbox.width;
    }
    

    无论怎么想,它都算不上优雅。但它会以相对较少的开销和不复杂的方式满足您的需求。

    Cufonized 字体

    如果您愿意考虑使用cufonized 字体,您可以计算给定文本字符串的大小,而完全不需要弄乱 DOM。事实上,这大概就是 canvas 的元素 measureText 方法在幕后所做的事情。给定一个导入的字体,你可以简单地做这样的事情(考虑这个 protocode!)

    //  font should be the result of a call to paper.[getFont][2] for a cufonized font
    function getCufonWidth( text, font, fontSize )
    {
        var textLength = text.length, cufonWidth = 0;
        for ( var i = 0; i < textLength; i++ )
        {
            var thisChar = text[i];
            if ( ! font.glyphs[thisChar] || ! font.glyphs[thisChar].w )
                continue;  //  skip missing glyphs and/or 0-width entities
            cufonWidth += font.glyphs[thisChar].w / font.face['units-per-em'] * fontSize;
        }
        return cufonWidth;
    }
    

    我真的很喜欢使用立体化字体——就它们以有趣的方式制作动画的能力而言,它们比文本更有用。但第二种方法可能比您需要或想要的更复杂。

    【讨论】:

      猜你喜欢
      • 2015-03-11
      • 2014-01-06
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      相关资源
      最近更新 更多