@nclslbrn/plot-writer
v0.1.10
Published
Write (SVG) text with JavaScript
Downloads
12
Maintainers
Readme
Plot-writer
An SVG text writer for plotter.
This library allows you to obtain an SVG plot from text, each glyph drawn with simple lines (no outlines).
The SVG font supports all characters of the Latin Extended-A alphabet.
Installation
npm i @nclslbrn/plot-writer
or if you prefer Yarn (like me)
yarn add @nclslbrn/plot-writer
Implementation
Single char
There is two main functions to convert text (single char) into vector. Both use the same arguments but they don't return the same thing.
Get SVG command
getGlyphPath(char, size, pos)
| parameter | type | decription |
| :---: | :---: | :---: |
| char | string | the char you want to transform into vector (⚠️ a single char) |
| size | array (optional) | width and heigth of the letter (default [1, 1]
) |
| pos | array (optional) | 2D coordinate of the letter (default [0, 0]
) |
Returns an array of <path d="*">
attribute (multiple lines).
import { getGlyphPath } from '@nclslbrn/plot-writer';
// setup you SVG before
const char = 'A'
const size = [1, 1];
const pos = [0, 0];
const svgsD = getGlyphPath(char, size, pos);
// A letter can have multiple lines so the function return an array of string
const paths = svgsD.map((d) => {
const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
p.setAttribute('d', d);
return p;
}
// You can now append p in your SVG or in a group
// paths.forEach((path) => svg.appendChild(path));
Get the vector path of a letter
getGlyphVector(char, size, pos)
| parameter | type | decription |
| :---: | :---: | :---: |
| char | string | the char you want to transform into vector (⚠️ a single char) |
| size | array (optional) | width and heigth of the letter (default [1, 1]
) |
| pos | array (optional) | 2D coordinate of the letter (default [0, 0]
) |
Returns an array of coordinate vectors, each line is in an array where 2D coordinates are stored ([[line1x1, line1y1], [line1x2, line2]...]...]
)
import { getGlyphVectors } from '@nclslbrn/plot-writer';
// setup you SVG, its attributes ()
const char = 'A'
const size = [1, 1];
const pos = [0, 0];
const letter = getGlyphVector(char, size, pos);
// A letter can have multiple lines so the function return an array of string
const paths = letter.forEach((line) => {
// You can alter each line before tracing the line,
// this function has been created to do so.
const d = line.reduce((d, v, i) =>
(d += `${i === 0 ? 'M' : 'L'}${v.join(',')}${i === line.length - 1 ? '' : ' '}`),
''
);
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', d);
// Include it in the svg
// svg.appendChild(path)
}
Paragraph (multiple lines w/ experimental hyphenation)
This font supports many language but hyphenation rules are relative to them, it's a basic feature. Maybe these functions could be enhanced and later take a language parameter (en/fr/es/it...) to target specific language hyphenation.
Get paragraph path
getParagraphPath(text, charsPerLine, hyphenFrom, textWidth, spacing)
| parameter | type | description |
| :---: | :---: | :---: |
| text | string | the text you want to write (you can include \r\n to add line return) |
| charsPerLine | number | number of characters per line |
| hyphenFrom | number | a threshold to find the right cut between words or where split a word (must be inferior to charsPerLine) |
| textWidth | number | maximum paragraph line length in pixels |
| spacing | array (optional) | [letter spacing, line spacing]
(default [1,1]
two factor relative to letter size (must be comprise between 0 & 1) |
Returns an object | key | type | description | | :---: | :---: | :---: | | paths | array | an array of SVG commands (string) for each line and letter in the paragraph. | | height | number | the height in pixels of the text block (to apply a translation afterwards, if you want it to be centered or not to stick out of the format) |
// import the lib, create your SVG element
const text = "The Latin script, also known as the Roman script, is a writing system based on the letters of the classical Latin alphabet, derived from a form of the Greek alphabet which was in use in the ancient Greek city of Cumae in Magna Graecia. The Greek alphabet was altered by the Etruscans, and subsequently their alphabet was altered by the Ancient Romans. Several Latin-script alphabets exist, which differ in graphemes, collation and phonetic values from the classical Latin alphabet.";
const textBlock = getParagraphPath(text, 16, 5, 960, [1, 0.6]);
textBlock.paths.forEach((d: string) => group.appendChild(pathFromD(d)));
Get paragraph vectors
getParagraphVector(text, charsPerLine, hyphenFrom, textWidth, spacing)
| parameter | type | description |
| :---: | :---: | :---: |
| text | string | the text you want to write (you can include \r\n to add line return) |
| charsPerLine | number | number of characters per line |
| hyphenFrom | number | a threshold to find the right cut between words or where split a word (must be inferior to charsPerLine) |
| textWidth | number | maximum paragraph line length in pixels |
| spacing | array (optional) | [letter spacing, line spacing]
(default [1,1]
two factor relative to letter size (must be comprise between 0 & 1) |
Returns an object
| key | type | description |
| :---: | :---: | :---: |
| paths | array | an array of coordinate vectors, each line is in an array where 2D coordinates are stored ([[line1x1, line1y1], [line1x2, line2]...]...]
) for each line and letter in the paragraph. |
| height | number | the height in pixels of the text block (to apply a translation afterwards, if you want it to be centered or not to stick out of the format) |
// import the lib, create your SVG element
const text = "The Latin script, also known as the Roman script, is a writing system based on the letters of the classical Latin alphabet, derived from a form of the Greek alphabet which was in use in the ancient Greek city of Cumae in Magna Graecia. The Greek alphabet was altered by the Etruscans, and subsequently their alphabet was altered by the Ancient Romans. Several Latin-script alphabets exist, which differ in graphemes, collation and phonetic values from the classical Latin alphabet.";
const textBlock = getParagraphVector(text, 16, 5, 960, [1, 0.6]);
textBlock.vectors.forEach((g) =>
g.forEach((l) => {
const path = document.createElementNS(namespace, 'path');
path.setAttribute(
'd',
l.reduce((d, v, i) =>
(d += `${i === 0 ? 'M' : 'L'}${v[0]},${v[1]}${i === l.length - 1 ? '' : ' '}`),
''
)
);
// add it to a group
// group.appendChild(path);
})
);
Why
I wanted to incorporate text into my plotter drawings, but I couldn't find any vector typography that could be used with JavaScript, so I decided to create this tool. Without this specific need I probably wouldn't have created any typography.
Already existing tools exist but doesn't fit all my need :
- p5js has a function (textToPoints) to export vector from text you get an outline and not the inner stroke, and if the text is small, that's a lot of point.
- An extension of Inkscape, Hershey text allows you transform a text into a vector (inner stroke) but it changes the size and appearance of the text.
I wanted something that could be integrated into my code so that I could be more precise about the position and size of the text. Using vectors from JS, it's also possible to apply transformations to them.
The library is published on npm, the typescript source is tranplied in several formats (CommonJS, UMD and EsNext).
Nicolas Lebrun | @nclslbrn