Reputation: 51671
I'm trying to work with an SVG polygon and javascript. I create a polygon and set its initial point list like this:
var polygon = document.createElementNS('http://www.w3.org/2000/svg','polygon');
polygon.setAttribute("points", "0,0 100,100 200,200");
now what do I do if I want to modify the 2nd point (100,100)? Right now I'm basically reconstructing the whole string again. But can we address "polygon.points" as an array somehow, or is it really just a plain simple string? This can work ok for very simple polygons, but if my polygon eventually has hundreds of point pairs, I'd hate to reconstruct the entire "points" attribute as a string every time I want to modify a single element.
Thanks
Upvotes: 17
Views: 21978
Reputation: 2206
You can access the individual point values using the SVG DOM:
var p = polygon.points.getItem(1);
p.x = 150;
p.y = 300;
(Assuming that your UA implements this interface.) See SVGPolygonElement
, SVGAnimatedPoints
, SVGPointList
and SVGPoint
.
I find though that using these SVG DOM interfaces (at least for me in Batik, in which I do most of my SVG stuff) is often not faster than just updating the attribute with string manipulation.
Upvotes: 28
Reputation: 114014
No way around it I'm afraid. You have to reconstruct the string again. But it's not difficult to wrap the whole thing in an object, something like:
function Polygon () {
var pointList = [];
this.node = document.createElementNS('http://www.w3.org/2000/svg','polygon');
function build (arg) {
var res = [];
for (var i=0,l=arg.length;i<l;i++) {
res.push(arg[i].join(','));
}
return res.join(' ');
}
this.attribute = function (key,val) {
if (val === undefined) return node.getAttribute(key);
node.setAttribute(key,val);
}
this.getPoint = function (i) {return pointList[i]}
this.setPoint = function (i,x,y) {
pointList[i] = [x,y];
this.attribute('points',build(pointList));
}
this.points = function () {
for (var i=0,l=arguments.length;i<l;i+=2) {
pointList.push([arguments[i],arguments[i+1]]);
}
this.attribute('points',build(pointList));
}
// initialize 'points':
this.points.apply(this,arguments);
}
var polygon = new Polygon(0,0, 100,100, 200,200);
polygon.setPoint(0, 50,10); // set point and automatically re-build points
polygon.points(50,50, 50,100, 200,100); // set everything
polygon.node; // refer to the actual SVG element
* not the best implementation but you get the idea.
Upvotes: 6
Reputation: 1302
You need to set all points at once, the performance is pretty solid, what you may want to do is manage the array outside and merge it on the setAttribute calls
Upvotes: 0
Reputation: 9810
You need to use setAttributeNS
. You'll probably want to cache that namespace in a variable somewhere so you don't have to keep typing it.
Upvotes: 1