将RaphaelJS打印限制在边界和位置

时间:2016-05-16 17:21:33

标签: raphael

我正在寻找一种更有效的方法来限制/设置Raphael中的文本。

我的文字可以写在一个盒子里。该文本应该居中(基于如果用户想要左/右移动文本可能会改变的数字),文本不能超出论文的界限。

这就是我现在所做的,而且性能不明显

// Build a path
var path = this.paper.print(x, x, text, font, size, 'middle')

// Center line by getting bounding box and shifting to half of that
var bb = path.getBBox()
path.transform('...T' + [-bb.width / 2, 0])

// Compare paper size vs bb
// if it goes beyond I adjust X and Y accordingly and redo the above

理想情况下,我想在打印之前预测文本的大小 - 我不确定这是否可行,因为它可能与字体有关。我已经找了一个禁止文字的命令,却看不到一个?

另一个想法是创建某种不会在屏幕上打印的影子纸,并在我呈现给用户之前使用它来确定尺寸。我不知道滞后在哪里 - 如果它在屏幕上呈现良好但如果它在创建svg的一般逻辑中那么那将不会有帮助。

我很感激建议

1 个答案:

答案 0 :(得分:0)

您可以使用opentype.js来测量文本,也可以使用Path.toPathData方法获取svg路径。不需要cufon编译的js字体。 对于文本度量,在DOM中的某处创建一个canvas元素。

<canvas id="canvas" style="display: none;"></canvas>

此函数将加载文本并计算宽度,高度

function measureText(text, font_name, size) {
    var dfd = $.Deferred();
    opentype.load('/fonts/' + font_name + '.ttf', function (err, font) {
        if (err) {
            dfd.reject('Font is not loaded');
            console.log('Could not load font: ' + err);
        } else {
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            var tmp_path = font.getPath(text, 100, 100, size);
            tmp_path.draw(ctx); // Draw path on the canvas
            var ascent = 0;
            var descent = 0;
            var width = 0;
            var scale = 1 / font.unitsPerEm * size;
            var glyphs = font.stringToGlyphs(text_string);
            for (var i = 0; i < glyphs.length; i++) {
                var glyph = glyphs[i];
                if (glyph.advanceWidth) {
                    width += glyph.advanceWidth * scale;
                }
                if (i < glyphs.length - 1) {
                    var kerningValue = font.getKerningValue(glyph, glyphs[i + 1]);
                    width += kerningValue * scale;
                }
                ascent = Math.max(ascent, glyph.yMax);
                descent = Math.min(descent, glyph.yMin);
            }
            return dfd.resolve({
                width: width,
                height: ascent * scale,
                actualBoundingBoxDescent: descent * scale,
                fontBoundingBoxAscent: font.ascender * scale,
                fontBoundingBoxDescent: font.descender * scale
            });
        }
    });
    return dfd.promise();
},

然后使用此函数获取文本尺寸:

$.when(measureText("ABCD", "arial", 48)).done(function(res) {
     var height = res.height,
     width = res.width;
     ...
});