8

As far as I know, there is currently no way to display SVG polygons in the Raphael Javascript library. I'm building an application that needs to read in SVGs and them display them in Raphael, however, many of these SVGs use polygons.

For example, I'm reading in an SVG with a polygon in this format:

<polygon points="260.5,627.75 259.563,628.313 258.625,628.563 258.25...

So, I'm wondering...is there a way to convert the polygon points into a path which I could draw in Raphael? I've seen a few applications using python and PHP, but so far I can't find anything that is strictly javascript.

Any help would be greatly appreciated. Thanks

James
  • 109,676
  • 31
  • 162
  • 175
Munzilla
  • 3,805
  • 5
  • 31
  • 35
  • You want a JavaScript solution? What is your source data: an actual SVG file with `` elements? And you want just the path's `d` attribute value back as the result? Or do you want the polygons converted in-place to new `` elements? – Phrogz Mar 13 '12 at 19:12

5 Answers5

15

See Paper.path. You can specify your own path. E.g. a red triangle:

paper.path('M 50 0 L 100 100 L 0 100 Z').attr('fill', 'red')

In response to your edit:

You should be able to take the points attribute, as a string, and replace all coordinates in the format x,y with L x,y -- that'll make a valid path for SVG. You might want a moveTo command initially though. So, this:

260.5,627.75 259.563,628.313 258.625,628.563

Would become:

M 260.5,627.75 L 259.563,628.313 L 258.625,628.563

Raphael seems to want integers, not decimals. So it would have to be:

M 260,627 L 259,628 L 258,628

To make this happen:

var polygonPoints = '260.5,627.75 259.563,628.313 258.625,628.563';
var convertedPath = polygonPoints.replace(/([0-9.]+),([0-9.]+)/g, function($0, x, y) {
    return 'L ' + Math.floor(x) + ',' + Math.floor(y) + ' ';
}).replace(/^L/, 'M'); // replace first L with M (moveTo)
James
  • 109,676
  • 31
  • 162
  • 175
  • I've edited the question. I'm looking more for a way to convert polygon points I have into a Raphael path. – Munzilla Mar 13 '12 at 19:12
  • 2
    Don't forget negative values in your regex. Also note that polygon/polyline points do not need to have a comma between them; they may use whitespace. Why `floor` instead of `round`? In SVG Path data you don't need to repeat the command name after the first occurrence. And finally, since polygons close themselves (as opposed to polylines) you need a `Z` or `z` on the end of your data. – Phrogz Mar 13 '12 at 19:51
3

The simplest (and most compact) solution is probably something like this, since points in a polygon/polyline are always absolute:

polygon:

var pathstr = "M" + yourPolygonElm.getAttribute("points") + "Z";

polyline:

var pathstr = "M" + yourPolylineElm.getAttribute("points");

This is because "L" is not really needed in the path string (the "d" attribute). "M" means first an absolute moveto, and then all coordinates that follow are implicit absolute linetos (or if you start with "m" then you get relative linetos).

Erik Dahlström
  • 59,452
  • 12
  • 120
  • 139
2

you can use http://readysetraphael.com/ to convert the whole SVG file to a raphael object, it's easier!!

Abdelali AHBIB
  • 602
  • 1
  • 7
  • 18
0

i came up with a solution, hope this helps:

this.createPolygon(304,0,0,500,912,500,608,0,'red');

createPolygon: function(x1,y1,x2,y2,x3,y3,x4,y4,color){
    return this.stage.path('M '+x1+' '+y1+' L '+x2+' '+y2+' L '+x3+' '+y3+' L '+x4+' '+y4+' Z').attr('fill',color);
}
user1971075
  • 128
  • 6
0

If you just want it to work:

var polys = document.querySelectorAll('polygon,polyline');
Array.prototype.forEach.call(polys,convertPolyToPath);

function convertPolyToPath(poly){
  var path = document.createElementNS('http://www.w3.org/2000/svg','path');
  var points = poly.getAttribute('points').split(/\s+|,/);
  var x0=points.shift(), y0=points.shift();
  var pathdata = 'M'+x0+','+y0+'L'+points.join();
  if (poly.tagName=='polygon') pathdata+='z';
  path.setAttribute('d',pathdata);
  poly.parentNode.replaceChild(poly,path);
  return path;
}

If you want to roll around in the SVG DOM:

function convertPolyToPath(poly){
  var path = document.createElementNS(poly.ownerSVGElement.namespaceURI,'path');
  var segs = path.pathSegList;
  var pts  = poly.points;
  for (var i=0,len=pts.numberOfItems;i<len;++i){
    var pt = pts.getItem(i);
    var func = i==0 ? 'createSVGPathSegMovetoAbs' : 'createSVGPathSegLinetoAbs';
    segs.appendItem(path[func](pt.x,pt.y))
  }
  if (poly.tagName=='polygon') segs.appendItem(path.createSVGPathSegClosePath());
  poly.parentNode.replaceChild(poly,path);
  return path;
}

Edit: See both of the above in action here:
http://phrogz.net/svg/convert_polys_to_paths.svg

Finally, if you have the points as a string (.getAttribute('points')) and just want the path data:

function svgPolyPointsToPathData(points,closePath){
  points = points.split(/\s+|,/);
  var pathdata = 'M'+points.shift()+','+points.shift()+'L'+points.join();
  if (closePath) pathdata+='z';
  return pathdata;
}
Phrogz
  • 296,393
  • 112
  • 651
  • 745