1

Hi all I'm getting successfully grabbing svg path data using opentype.js but having trouble using that data with svg.js to render the path:

Below is my code which currently creates an svg with an empty group <g></g> where I was expecting the group to wrap my path data.

I read on another post that I should be using SVG.adopt() (as I have tried below) to no avail. Thanks in advance

const svg = new SVG().addTo('body').attr({
  viewBox: '0 0 100 100'
})

const createShape = (font,content) => {
  const fontPaths = font.getPaths(content,20,20,100)
  const paths = fontPaths.map(fontPath => {
    console.log(fontPath.toSVG())
    const path = SVG.adopt(fontPath.toSVG())
    // const svgPath = SVG(path)
    // // svgPath.fill('black')
    console.log(path)
    return path
  })
  const group = svg.group()
  group.add(paths).attr({
    fill: 'black'

  })
      return group
}

const draw = (font) => {
  createShape(font,'hello')
}

opentype.load('https://assets.codepen.io/1070/basiersquare-bold-webfont.woff',(err,font) => draw(font))
James
  • 1,355
  • 3
  • 14
  • 38

1 Answers1

0

opentype.js method fontPath.toSVG() will return svg markup – not any nodes.
Whereas group.add(paths) expects the variable "paths" to conatain nodes for appending.

If you don't mind I'd suggest a plain js approach for svg generation.

Example: get glyph paths and append svg

const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
g.setAttribute('fill', 'black');
document.body.appendChild(svg);
svg.appendChild(g);

const createShape = (font, content) => {
  let pathMarkup = '';
  const fontPaths = font.getPaths(content, 0, 100, 100)
  const paths = fontPaths.map(fontPath => {
    let path = fontPath.toSVG();
    pathMarkup += path;
  })
  g.insertAdjacentHTML('beforeend', pathMarkup);
  //adjust viewBox
  let viewBox = svg.getBBox();
  svg.setAttribute('viewBox', [0, 0, (viewBox.width + viewBox.x).toFixed(2), (viewBox.height + viewBox.y).toFixed(2)].join(
    ' '));
}

const draw = (font) => {
  createShape(font, 'hello')
}

opentype.load('https://fonts.gstatic.com/s/firasans/v15/va9B4kDNxMZdWfMOD5VnZKveRhf8.woff', (err, font) => draw(font))
svg{
width: 50vw;
border: 1px solid #ccc
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.1.2/svg.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>

The above example is basically

  • appending svg and group element to DOM
  • concatenating the path markup returned by opentype.js
  • inserting the markup to svg group
  • adjusting the svg viewBox to avoid overflows (using getBBox() to get appropriate width and height values)

Edit: svg.js approach

As @Fuzzyma pointed out – my answer might have been too biased.

const svg = new SVG().addTo('body');
const group = svg.group();
const createShape = (font,content) => {
    let pathString = '';
  const fontPaths = font.getPaths(content,0,100,100)
  const paths = fontPaths.map(fontPath => {
    let path = fontPath.toSVG();
    pathString += path;
    return pathString
  })
  group.svg(pathString).attr({
    fill: 'black'
  })
      return group
}

svg.attr({
  viewBox: '0 0 226.10 101.50'
})

const draw = (font) => {
  createShape(font,'hello')
}

opentype.load('https://assets.codepen.io/1070/basiersquare-bold-webfont.woff',(err,font) => draw(font))
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.1.2/svg.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
herrstrietzel
  • 11,541
  • 2
  • 12
  • 34
  • 1
    I don't see how SVG(svg string).addTo(container) is complicated – Fuzzyma Feb 24 '22 at 22:48
  • @Fuzzyma: OK – you got me! But I still don't see the advantages of libraries like svg.js when it comes to svg creation based on externally retrieved path data. **I see the advantages when elements are created from scratch**. Besides natively supported methods (like getBBox(), getPointAtLength(), isPointInStroke ect.) also provide way better documentation: e.g. mdn docs with multiple examples instead of lackluster library/framework doc one-liners (often outdated). What's the abstracted equivalent of `getTotalLength()` in library X/Y again? – herrstrietzel Feb 25 '22 at 01:06
  • @Fuzzyma: Answer updated (stripping the opinionated parts, adding an svg.js api based example). Hey, next time, you just answer directly ;) (I should also check previous rants regarding paper.js – probably some devs are also not pleased.) – herrstrietzel Feb 25 '22 at 01:55
  • No problem. I kinda agree :). I try to answer as much as possible but just don't have that much time anymore :/. Maybe I will add one later :) – Fuzzyma Feb 25 '22 at 05:55