JavaScript text editor for SVG
Alexey Boyko
Posted on April 22, 2022
Fig 1. SVG text editor with support for selection, copy, paste. Works on PC and mobile.
The article describes how to make a text editor. Source code is attached.
Multiline text in SVG
SVG does not have a line break character. For multiline text SVG uses <tspan>
.
Fig 2. Multiline text, third line is empty
<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>
Listing 1. Multiline text in SVG. The third line is empty. The line height is 20px.
The position of the <tspan>
elements is relative to the top edge of the <text>
. The value of the 'y' attribute must be calculated.
The 'y' attribute calculations can be avoided. Listing 2 gives the same result. The 'dy' attribute is used with a fixed value. 'dy' indicates the position relative to the previous element.
<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>
Listing 2. Multiline text in SVG. The third line is empty. The line height is 20px. The indent is set relative to the previous element.
Forming multi-line markup with JavaScript
The function below renders markup with a fixed 'dy' attribute. The markup is obtained as in Listing 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('');
}
Listing 3. Function makes multi-line markup
In Figure 1, when you add a line, the text moves up. Thus the text is always in the center of the circle. Listing 4 shows how this is implemented:
/**
* @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;
}
}
Listing 4. The function inserts text into SVG. When specifying verticalMiddle , the text is centered vertically.
Text editor
The editor must support all standard features:
- text navigation, selection, insertion, copying;
- autocorrect, spell check;
- work on PC and mobile
For standard features, there is a standard <textarea>
.
The algorithm of the editor:
- A transparent
<textarea>
is positioned above the text. The<textarea>
font is also transparent; - On input, the svgTextDraw from Listing 4 is called;
- The dimensions and position of the
<textarea>
are recalculated.
The algorithm is implemented in the textareaCreate function. Function code in a separate file on GitHub.
An editor can be attached to any <text>
element:
const textEditor = textareaCreate(
// {SVGTextElement}
textEl,
// text params
{ lineHeight: 20, verticalMiddle: 10 },
// init value
'init text',
// onchange
val => {...},
// onblur
val => {...});
ā¦
// delete textarea
textEditor.remove();
Listing 5. Creating a text editor for <text>
Other articles about dgrm.net
- JavaScript SVG diagram editor 3.9 KB (open source library)
- JavaScript diagram editor that renders diagrams from PNG images (open source)
- JavaScript text editor for SVG
- Flowchart editor UI
- JavaScript: Zoom like in maps for SVG/HTML
How to support the project
Posted on April 22, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 16, 2024