npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nclslbrn/plot-writer

v0.1.10

Published

Write (SVG) text with JavaScript

Downloads

10

Readme

Plot-writer

Dynamic JSON Badge 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).

a plot made with PlotWriter

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