0

I have different svg strings generated by svg.js in browser (correct one) and at node (incorrect and with exsessive inner svg element) Here is my code for browser:

let size = { width: 512, height: 512 };
let entity = { x: 232,
  y: 162,
  rx: 137,
  ry: 146,
  a: 13,
  strokeColor: 0,
  strokeAlfa: 0.8,
  strokeWidth: 2,
  fillColor: 10,
  fillAlfa: 0.8 };
let draw = SVG(document.documentElement).size(size.width,size.height);
  let svg = draw
  .rect(size.width,size.height).fill("#fff");
  draw
  .ellipse(entity.rx,entity.ry)
  .move(entity.x,entity.y)
  .rotate(entity.a)
  .stroke({
    color:'rgb('+entity.strokeColor+','+entity.strokeColor+','+entity.strokeColor+')',
    opacity:entity.strokeAlfa,
    width:entity.strokeWidth
  })
  .fill({
    color:'rgb('+entity.fillColor+','+entity.fillColor+','+entity.fillColor+')',
    opacity:entity.fillAlfa});
    console.log(draw.svg());
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.3/svg.min.js"></script>
svg generated in browser is clean:
<svg id="SvgjsSvg1006" width="512" height="512" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1007"></defs>
<rect id="SvgjsRect1008" width="512" height="512" fill="#ffffff"></rect>
<ellipse id="SvgjsEllipse1009" rx="68.5" ry="73" cx="300.5" cy="235" transform="matrix(0.9743700647852352,0.224951054343865,-0.224951054343865,0.9743700647852352,60.56529330284505,-61.57475705486172)" stroke-opacity="0.8" stroke="#000000" stroke-width="2" fill-opacity="0.8" fill="#0a0a0a"></ellipse>
</svg>

But when I do same at node:

  const window   = require('svgdom');
  const SVG      = require('svg.js')(window);
  const document = window.document;


let size = { width: 512, height: 512 };
let entity = { x: 232,
  y: 162,
  rx: 137,
  ry: 146,
  a: 13,
  strokeColor: 0,
  strokeAlfa: 0.8,
  strokeWidth: 2,
  fillColor: 10,
  fillAlfa: 0.8 };
let draw = SVG(document.documentElement).size(size.width,size.height);
  let svg = draw
  .rect(size.width,size.height).fill("#fff");
draw
.ellipse(entity.rx,entity.ry)
.move(entity.x,entity.y)
.rotate(entity.a)
.stroke({
  color:'rgb('+entity.strokeColor+','+entity.strokeColor+','+entity.strokeColor+')',
  opacity:entity.strokeAlfa,
  width:entity.strokeWidth
})
.fill({
  color:'rgb('+entity.fillColor+','+entity.fillColor+','+entity.fillColor+')',
  opacity:entity.fillAlfa});
console.log(draw.svg());

I have this svg string as an output:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="512" height="512">
<defs id="SvgjsDefs1001"></defs>
<svg id="SvgjsSvg1002" width="2" height="0" style="overflow: hidden; top: -100%; left: -100%; position: absolute; opacity: 0">
<polyline id="SvgjsPolyline1003" points="0,0"></polyline>
<path id="SvgjsPath1004" d="M0 0 "></path></svg>
<rect id="SvgjsRect1006" width="512" height="512" fill="#ffffff"></rect>
<ellipse id="SvgjsEllipse1007" rx="68.5" ry="73" cx="300.5" cy="235" transform="matrix(0.9743700647852352,0.224951054343865,-0.224951054343865,0.9743700647852352,60.56529330284505,-61.57475705486172)" stroke-opacity="0.8" stroke="#000000" stroke-width="2" fill-opacity="0.8" fill="#0a0a0a"></ellipse>
</svg>

As you see - there is inner svg element with polyline and path inside. It looks like should be invisible, and I would ignore it, but later I load this svg file into Graphicsmagic (gm) to compare, and gm doesn't like this polyline very much:

Error: gm compare: Non-conforming drawing primitive definition (polyline).

Is it a bug of mine, svgjs or svgdom?

--- additional notes:

Even an empty svg with no manipulations have this annoying polyline:

  const window   = require('svgdom');
  const SVG      = require('svg.js')(window);
  const document = window.document;

let draw = SVG(document.documentElement);
console.log(draw.svg());

SVG:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1001"></defs>
<svg id="SvgjsSvg1002" width="2" height="0" style="overflow: hidden; top: -100%; left: -100%; position: absolute; opacity: 0">
<polyline id="SvgjsPolyline1003" points="0,0"></polyline>
<path id="SvgjsPath1004" d="M0 0 "></path></svg></svg>

--- update 2

As I see in the sources of svg.js, this hidden poly was made intentially May be in case of svgdom some cleanup code was not called? Can I do it manually as a workaround?

wout
  • 2,477
  • 2
  • 21
  • 32
Yuri Gor
  • 1,353
  • 12
  • 26

2 Answers2

0

If someone faced with issue, here is a workaround:

Right before exporting SVG string you can just remove this hidden element

_.each(document.querySelectorAll('polyline[points="0,0"]'),function(pl){
    let todel = pl.parentNode;
    todel.parentNode.removeChild(todel);
  });

See details and more options here: https://github.com/svgdotjs/svgdom/issues/13

Yuri Gor
  • 1,353
  • 12
  • 26
  • 1
    You may be want to go the svg.js way of doing this and do: `canvas.select(querySelector).remove()`. Looks a bit more nice :) – Fuzzyma Mar 05 '18 at 21:36
0

The answer to this question is simple but a bit annyoing.

svg.js generates a so called parser in the dom. Its just an svg document which is used to calculate bounding boxes of path or point arrays or to get the bbox of an invisible element. In html this parser is appended to the body (so its not in your main svg). However, in standaline svgs (which svgdom is), the parser has to go somewhere. So its added to the main svg.

And thats what you are seeing there. Its the parser. Its invisible anyway so it wont show up. But yes - its cluttering the source code. Unfortunately there is no workaround for this issue because browser just do not want give you the bbox of invisible elements so we need it.

Hope I could help!

Fuzzyma
  • 7,619
  • 6
  • 28
  • 60
  • I didn't care about this invisible element until I tried to render such svg with graphicsmagic. This lib outputs an error. I know generated svg is correct according to specs, but graphicsmagic hates polylines with one point very much, it's maybe something personal, who knows. – Yuri Gor Mar 05 '18 at 20:01
  • Then removing it is the only option. From your answer I figure that you solved that already :) – Fuzzyma Mar 05 '18 at 21:37