14

Is there a D3.js way to convert a text element into a path element?

So when I grasp the generated svg, I could keep my the texts shapes.

altocumulus
  • 21,179
  • 13
  • 61
  • 84
Hugolpz
  • 17,296
  • 26
  • 100
  • 187
  • Maybe [this question](http://stackoverflow.com/questions/9702976/raphael-js-convert-text-to-path) helps? – Lars Kotthoff Oct 28 '14 at 09:05
  • 3
    To answer your question, there is no D3.js way to convert text characters to paths. – Stephen Thomas Jan 31 '15 at 20:49
  • Reading between the lines, It seems like you're concerned about the SVG looking different in systems that don't have the correct fonts? Have you considered embedding the fonts used into the SVG? I've done a quick search and this is discussed in this question over at Graphic Design SE http://graphicdesign.stackexchange.com/questions/5162/how-do-i-embed-google-web-fonts-into-an-svg – Joe Feb 02 '15 at 02:29
  • Yes, i worry about looks in other people computer. As i speak about Chinese open font (17MB), embedding will not suit my need.... but will be a relevant answer for the SO community :) – Hugolpz Feb 02 '15 at 03:38
  • Alternatively, could you use something like [inkscape](https://inkscape.org/) to convert the text you want to paths, and then add these paths to the svg, either by hand or in JavaScript? This would limit the number of phrases you could represent to those you had paths for, but it's the only thing I can think of that doesn't require the user to download the font (embedded or otherwise) – Joe Feb 02 '15 at 03:55
  • @Joe-JW718 : not a programatical way, but possible indeed. – Hugolpz Feb 02 '15 at 03:56
  • 1
    @Joe-JW718 & Hugolpz: Inkscape actually has a [command-line interface](https://inkscape.org/doc/inkscape-man.html) which should be able to do the conversion programmatically, if you can integrate it within the rest of the workflow. – AmeliaBR Feb 05 '15 at 01:49

4 Answers4

28

There is no way in JavaScript (d3 or any other tool) to access the vector path information about the shape of individual letters in system or web fonts. It's a requested feature for SVG 2, but there are no firm proposals for how it would work.

The Raphael method described in the question linked by Lars Kotthoff uses a font object that has already been converted to JavaScript, using the Cufon font generator utility. Unfortunately, Cufon was designed for the old IE VML language, not SVG, so you would need to add an extra conversion (or use Raphael) to convert to SVG path data.

For working with SVG, it might be just as easy to use a general font-converter tool to convert to SVG fonts, then extract the glyph data and transform it (to the correct size and to flip the y-axis). Alternately, if you're working on a server you could look into using a low-level graphics library such as Cairo which can do text-to-path conversion. Unfortunately, SVG font support in browsers is so poor that you can't use it to embed the font data directly. (Even assuming you had the rights to distribute the font, but were not using web fonts because of other reasons).

Update: The mention of Inkscape in the comments reminded me that Inkscape also has a command-line interface to convert/export SVG files. You may be able to use it in a server workflow; text-to-path is one of the export options. You'd have to figure out a way to set it up so the Inkscape program on your server has access to the complete font, and then shuttle the SVG created by your d3 routine through Inkscape with options like:

inkscape TEMP.FILENAME --export-plain-svg=FILENAME --export-text-to-path

The only text-to-image option in the DOM is HTML canvas; you can write on the canvas and then grab the image data. But that would be a PNG image, not a vector.

However, I would also urge you to consider whether you really need the exact shapes of the letters in a specific font, and if it is worth losing the functionality, accessibility, and SEO benefits that come from using text as text.

Community
  • 1
  • 1
AmeliaBR
  • 27,344
  • 6
  • 86
  • 119
  • +1 and thanks for the feedback. My main question is to keep the shape while generating programmatically hundreds of svgs. I would prefer to output svg, but outputing large rasters could be a lead / possibility as well. – Hugolpz Feb 05 '15 at 00:14
  • Thanks for this nice answer. Bounty is yours, as well as a friendly thank you ! – Hugolpz Feb 07 '15 at 20:08
  • 1
    Thanks @Hugolpz. Sorry there wasn't the easy solution you were hoping for, but hopefully you can now investigate other ways to solve the problem. – AmeliaBR Feb 08 '15 at 00:09
  • A use case for NOT using text as text is to generate animations of text. – David Spector Jan 30 '19 at 16:13
10

There is a node module called text-to-svg that claimed to do so:

Convert text to SVG path without native dependencies.

Example

const TextToSVG = require('text-to-svg');
const textToSVG = TextToSVG.loadSync();

const attributes = {fill: 'red', stroke: 'black'};
const options = {x: 0, y: 0, fontSize: 72, anchor: 'top', attributes: attributes};

const svg = textToSVG.getSVG('hello', options);

console.log(svg);
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178
  • 2
    Maybe worth mentioning this module as well as many other -- even browser based -- utilities are using incredible https://opentype.js.org/ library. ("Random" web based app for example: https://formito.com/tools/favicon ) – myf Nov 02 '20 at 12:29
  • 1
    But this will not work for Unicode Chars. Correct ? – Mrug Nov 12 '20 at 08:24
  • @Mrug I'm using it to generate a ruby font for various scripts (e.g. Chinese with pinyin annotation) https://github.com/parlr/ruby-font-creator/blob/master/src/ruby.js – Édouard Lopez Nov 19 '20 at 12:07
3

Try my lib - svg-text-to-path

  • support otf/ttf fonts;
  • integrated with Google Fonts;
  • support tspan;
  • different fonts library;
  • support CSS text-anchor and dominant-baseline properties;
  • support nodejs and browser runtime;
PaulZi
  • 51
  • 2
  • Whoa! That's really impressive - especially the [fontkit demo](https://paulzi.github.io/svg-text-to-path/index.html)! Maybe you could provide a stripped down usage example as a snippet. Does svg-text-to-path also support `` conversions? – herrstrietzel Mar 28 '23 at 15:35
  • Hi! `let session = new Session('sample'); await session.replaceAll(); console.log(session.getSvgString());` `` is currently not supported. – PaulZi Mar 30 '23 at 06:25
2

All these text-to-svg node modules mentioned above use opentype.js

I decided to use it directly with great success:

https://github.com/opentypejs/opentype.js#pathtosvgdecimalplaces

Ray Hulha
  • 10,701
  • 5
  • 53
  • 53