Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading SVG in KineticJS

Tags:

svg

kineticjs

I am trying to load SVG file and want to display it on canvas using KineticJS (KJS), so wanted to know whether it is possible to show any SVG file with random shapes and paths in it, in canvas using KJS?

Now SVGs exported via different software also differ a lot, let say for example the in the SVG exported via Adobe Illustrator has fill, stroke, stroke-width etc. As attributes to their respective tags, while the SVG exported via Inkscape has all of these I.e. Fill, stroke, stroke-width etc. As a string value for the "style" attribute to their respective tags.

So I am at the verge of writing a SVG parser of my own, specific to format of SVG exported by AI and then use it to redraw the SVG on canvas via KJS. But before doing that, I just wanted to check:

  1. Is there any tool available out there, which could convert all the primitive (line, rect, circle, etc) tags as path tag? I.e. Instead of rect & ellipse tag, they are converted to their equivalent path tags.
  2. Is there any alternative way of loading SVG onto canvas other than KJS?
like image 708
Pseudocode Avatar asked Feb 19 '23 09:02

Pseudocode


2 Answers

Unfortunately you can't drawImage SVG into Canvas (test).

But you can use canvg to draw the SVG in a custom KineticJS shape (test):

var drawSvg = new Kinetic.Shape ({
  x: 10, y: 10,
  drawFunc: function (canvas) {
    canvas.getContext().drawSvg (svgSource, 0, 0, 25, 25)
  }
}); layer.add (drawSvg)
like image 53
ArtemGr Avatar answered Apr 02 '23 17:04

ArtemGr


Actually it is possible to drawImage() a SVG into Canvas (the code from ArtemGr is working in FF and Chrome for me).

But in Chrome you will experience the Origin Policy error (there is a bug reported in https://bugs.webkit.org/show_bug.cgi?id=17352).

I've tried to use canvg with kinetic, but I found 2 problems:

  1. It is very slow when Kinetic's listening is enabled;
  2. It's quality of render is very poor if you need to scale the image;

A solution I've found is to use the SVG render of fabricjs, that proved to be very superior. The code looks like this:

var fabricSvg;
// uses the fabric SVG engine
fabric.loadSVGFromUrl(svgSource, function(objects, opts) {
  if (objects.length > 1) 
    fabricSvg = new fabric.PathGroup(objects, opts);
  else
    fabricSvg = objects;

  fabricSvg.originX = 'left';
  fabricSvg.originY = 'top';

  var drawSvg = new Kinetic.Shape({
    x: 10, y: 10,
    drawFunc: function(canvas) {
      // use fabric SVG engine with Kinetic canvas context
      fabricSvg.render(canvas.getContext());
    }
  });
  layer.add(drawSvg);
});

That way we can use the Kinetic animation engine, that has a better performance than fabric's, and the Fabric's SVG render module.

like image 21
charlesschaefer Avatar answered Apr 02 '23 16:04

charlesschaefer