В статье описано, как сделать текстовый редактор. Исходный код прилагается.
Многострочный текст в SVG
SVG не имеет символа разрыва строки. Для многострочного текста SVG использует ‹tspan›.
<text x="0" y="0"> <tspan x="0" y="0">Line 1</tspan> <tspan x="0" y="20px">Line 2</tspan> <!-- Line 3 is empty <tspan x="0" y="40px"></tspan> --> <tspan x="0" y="60px">Line 4</tspan> </text>
Листинг 1. Многострочный текст в формате SVG. Третья строка пуста. Высота строки составляет 20 пикселей.
Положение элементов ‹tspan› относительно верхнего края ‹текста›. Значение атрибута «y» должно быть рассчитано.
Вычисления атрибута «y» можно избежать. Листинг 2 дает тот же результат. Атрибут «dy» используется с фиксированным значением. ‘dy’ указывает позицию относительно предыдущего элемента.
<text x="0" y="0"> <tspan x="0" dy="0">Line 1</tspan> <tspan x="0" dy="20px">Line 2</tspan> <tspan x="0" dy="20px" visibility="hidden">.</tspan> <tspan x="0" dy="20px">Line 4</tspan> </text>
Листинг 2. Многострочный текст в формате SVG. Третья строка пуста. Высота строки 20px. Отступ задается относительно предыдущего элемента.
Формирование многострочной разметки с помощью JavaScript
Функция ниже отображает разметку с фиксированным атрибутом «dy». Разметка получается как в листинге 2.
/** * create multiline tspan markup * @param {string} str * @param {number} lineHeight * @returns {string} */ function svgStrToTspan(str, lineHeight) { return str.split('\n').map((t, i) => { return `<tspan x="0" dy="${i === 0 ? '0' : `${lineHeight}px`}" ${t.length === 0 ? 'visibility="hidden"' : ''}> ${t.length === 0 ? '.' : escapeHtml(t).replaceAll(' ', ' ')} </tspan>`; }).join(''); }
Листинг 3. Функция делает многострочную разметку
На рис. 1 при добавлении строки текст перемещается вверх. Таким образом, текст всегда находится в центре круга. В листинге 4 показано, как это реализовано:
/** * @param {SVGTextElement} textEl target text element * @param {string} str * @param {{lineHeight:number, verticalMiddle?:number}} param * @returns {void} */ export function svgTextDraw(textEl, str, param) { textEl.innerHTML = svgStrToTspan(str, param.lineHeight); if (param.verticalMiddle != null) { textEl.y.baseVal[0].value = param.verticalMiddle - textEl.getBBox().height / 2; } }
Листинг 4. Функция вставляет текст в SVG. При указании verticalMiddle текст выравнивается по центру по вертикали.
Текстовый редактор
Редактор должен поддерживать все стандартные возможности:
- навигация по тексту, выделение, вставка, копирование;
- автокоррекция, проверка орфографии;
- работа на ПК и мобильных устройствах.
Для стандартных функций есть стандартное ‹текстовое поле›.
Алгоритм редактора:
- Прозрачное ‹textarea› расположено над текстом.
Шрифт ‹textarea› также прозрачный; - При вводе вызывается svgTextDraw из листинга 4;
- Размеры и положение ‹textarea› пересчитываются.
Алгоритм реализован в функции textareaCreate. Код функции в отдельном файле на GitHub.
Редактор можно прикрепить к любому элементу ‹text›:
const textEditor = textareaCreate( // {SVGTextElement} textEl, // text params { lineHeight: 20, verticalMiddle: 10 }, // init value 'init text', // onchange val => {...}, // onblur val => {...}); … // delete textarea textEditor.remove();
Листинг 5. Создание текстового редактора для ‹text›
Другие статьи о dgrm.net
- Редактор диаграмм JavaScript SVG 3,9 КБ (библиотека с открытым исходным кодом)
- Редактор диаграмм JavaScript, отображающий диаграммы из изображений PNG (с открытым исходным кодом)