Получение размера текста без использования функции boundingBox в библиотеке Raphael javascript

1

Я пытаюсь создать несколько кнопок с текстом в javascript, используя библиотеку Rahpael. Я хотел бы знать размер стилизованного текста, прежде чем рисовать, чтобы избежать этого, чтобы я мог создать правильный фон (кнопка). Также я хотел бы избежать рисования текста за пределами холста/бумаги (позиция текста - это положение его центра).

Я могу использовать метод Raphaels getBBox(), но мне нужно создать (нарисовать) текст на первом месте, чтобы сделать это. Поэтому я рисую текст, чтобы получить размер, чтобы он мог нарисовать его в правильном положении. Это уродливо. Поэтому я ищу общий метод оценки метрик стилизованного текста для заданного шрифта, размера шрифта, семейства...

Есть возможность сделать это, используя холст HTML5 http://www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/, но Raphael не использует холст. Есть ли возможность получить текстовые показатели с помощью Raphael или простого Javascript?

Теги:
text
metrics
size
raphael

2 ответа

4
Лучший ответ

Я знаю, что это кажется небрежным, но у вас не должно возникнуть проблемы с рисованием текста, его измерением, затем рисованием кнопки и перемещением метки. Чтобы быть в безопасности, просто снимите его с экрана:

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);    
}
  • 0
    Большое спасибо за ответ. Cufonized шрифты не приходят в очередь, потому что мне нужно, чтобы текст вел себя как обычный текст, чтобы его можно было выбирать и поддерживать копирование. Кроме того, мысль, которую я еще не рассматривал, - это перенос текста. Ваше второе предложение с объектом (картой), содержащим ширину букв, напечатанных определенным шрифтом и размером шрифта, весьма полезно для этого. Возникает вопрос, не существует ли другого лучшего решения для этого, чем использование текстового объекта Raphaels, например, объединение Raphael и нормальных div-ов ...
  • 0
    Да, я почти всегда использую регулярные div над текстовыми полями SVG / VML, особенно для переноса (и полного доступа к CSS). Можете ли вы принять ответ, если он работает для вас? Нужно подтверждение моей самооценки;)
Показать ещё 3 комментария
5

Есть несколько способов разрезать эту кошку. Два очевидных легко прийти на ум.

Внештатная техника линейки

Этот самый простой. Просто создайте текстовый элемент за пределами canvas 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 Font

Если бы вы захотели использовать шрифт cufonized, вы могли бы рассчитать размер данной текстовой строки без необходимости связываться с DOM вообще. На самом деле это, вероятно, примерно то, что делает элемент canvas measureText за кулисами. Учитывая импортированный шрифт, вы просто сделаете что-то вроде этого (подумайте об этом протокоде!)

//  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;
}

Мне очень нравится работать с cufonized fonts - с точки зрения их способности к анимации интересными способами, они гораздо полезнее, чем текст. Но этот второй подход может быть более сложным, чем вам нужно или хотите.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню