user1475128
user1475128

Reputation: 35

Plot points using SVG path in Fabric JS

I need to be able to plot points as an SVG path on HTML canvas. I am using Fabric JS with OpenSeaDragon. The path I have generated works on Firefox but does not work on any other browser. It seems that other browsers expect a continuous path and will only render the last point. I cannot use fabric.circle as I need to render 1000's of points.

Is anyone familiar with this problem, and know a way i can generate an SVG path so that it can be rendered x-browser. The format that works on firefox is:

Move, Line, Close and repeat for as many points. e.g: M 25333 15819 L 25333 15819 Z
M 25116 15764 L 25116 15764 Z
M 24396 15437 L 24396 15437 Z
M 23976 16585 L 23976 16585 Z
M 23976 16579 L 23976 16579 Z
M 23977 16576 L 23977 16576 Z

Many thanks!

Upvotes: 1

Views: 1398

Answers (1)

markE
markE

Reputation: 105015

Your SVG data commands are oddly formed

Your M & L values are the same for each subpath so you're not really drawing lines, you're drawing points. From your question I assume this is what you want ... to draw a series of points with each point defined by one M L command.

Getting points from SVG commands

Parse your Svg M+L commands into Canvas moveTo+lineTo commands and put those canvas commands into a single beginPath.

Your example data has a simple an uniform structure so you could parse it with .split. If your actual data is more complex you can use regEx to parse it.

var data='M 25333 15819 L 25333 15819 Z  M 25116 15764 L 25116 15764 Z  M 24396 15437 L 24396 15437 Z M 23976 16585 L 23976 16585 Z  M 23976 16579 L 23976 16579 Z  M 23977 16576 L 23977 16576 Z';

var canvasPts=[];
var dataCmds=data.split('M');
for(var i=1;i<dataCmds.length;i++){
    var cmd=dataCmds[i].split(' ');
    canvasPts.push({x:parseInt(cmd[1]),y:parseInt(cmd[2])});
}

Once you parse out your points-set you can draw them with Fabric.Circles or with Fabric.Polyline if you want the points connected.

Here's example code and a Demo (using native canvas):

Your coordinates are very large so this demo divides each coordinate by 100

Note: the points are drawn in the lower right of the canvas so you will have to scroll the Stack Snippet window down or view it in full-page mode.

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var data='M 25333 15819 L 25333 15819 Z  M 25116 15764 L 25116 15764 Z  M 24396 15437 L 24396 15437 Z M 23976 16585 L 23976 16585 Z  M 23976 16579 L 23976 16579 Z  M 23977 16576 L 23977 16576 Z';

var canvasPts=[];
var dataCmds=data.split('M');
for(var i=1;i<dataCmds.length;i++){
    var cmd=dataCmds[i].split(' ');
    canvasPts.push({x:parseInt(cmd[1]),y:parseInt(cmd[2])});
}

var ptRadius=2;
ctx.beginPath();
for(var i=0;i<canvasPts.length;i++){
    var x=canvasPts[i].x/100;
    var y=canvasPts[i].y/100;
    ctx.moveTo(x+ptRadius,y);
    ctx.arc(x,y,ptRadius,0,Math.PI*2);
}
ctx.fill();
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

Upvotes: 1

Related Questions