2010-01-28 25 views
18

Estoy tratando de trabajar con un polígono SVG y javascript. Puedo crear un polígono y establecer su lista de puntos inicial de la siguiente manera:Trabajando con elementos del polígono SVG

var polygon = document.createElementNS('http://www.w3.org/2000/svg','polygon'); 
polygon.setAttribute("points", "0,0 100,100 200,200"); 

ahora ¿qué hago si quiero modificar el segundo punto (100,100)? En este momento, básicamente estoy reconstruyendo toda la cadena nuevamente. ¿Pero podemos abordar "polígono.puntos" como una matriz de alguna manera, o es realmente una simple cadena simple? Esto puede funcionar bien para polígonos muy simples, pero si mi polígono finalmente tiene cientos de pares de puntos, odiaría reconstruir todo el atributo de "puntos" como una cadena cada vez que quiero modificar un solo elemento.

Gracias

Respuesta

6

hay manera de evitarlo, me temo. Tienes que reconstruir la cadena de nuevo. Pero no es difícil para envolver todo el asunto en un objeto, algo así como:

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 

* no es la mejor aplicación, pero se entiende la idea.

+0

Gracias se ve muy bien, veo qué quieres decir. Trataré de implementar uno optimizado luego sobre una representación 'vanilla'. – user246114

+0

Si ejecuto este código en Chrome 58, aparece un error "Unbeught ReferenceError: node no está definido". Esto sucede solo la consola de desarrollo de Chrome también, así que creo que es inherente al código –

+0

@ColinD Se supone que es 'this.node'. Este código nunca fue pensado para ser usado tal como está. Es para ilustrar la idea de que usted puede implementar código fácilmente. para administrar los polígonos usted mismo. – slebetman

1

Es necesario utilizar setAttributeNS. Es probable que desee almacenar en caché ese espacio de nombres en una variable en alguna parte para que no tenga que seguir tipeando.

+0

¿Tenemos que usar setAttributeNS/getAttributeNS cada vez que establecemos un atributo con un elemento SVG? Por ejemplo, incluso si queremos modificar el parámetro 'x' de un rect? (rect.setAttributeNS (ns, 'x', 22)? Gracias – user246114

+2

@ unknown-google: no, usando setAttribute() está bien. – heycam

0

Es necesario configurar todos los puntos a la vez, el rendimiento es bastante sólido, lo que es posible que desee hacer es administrar la matriz exterior y fusionarla en el setAttribute llama

+0

Ok, si quiero una solución genérica, para modificar el enésimo par, necesito analizar la cadena yo mismo, encontrarla, luego modificarla. Esa clase de olor apesta, pero creo que puedo mantener los pares de puntos como una estructura separada, ¡como que apesta, lo hicieron así! Gracias – user246114

25

Se puede acceder a los valores de los puntos individuales utilizando el DOM SVG:

var p = polygon.points.getItem(1); 
p.x = 150; 
p.y = 300; 

(Asumiendo que su UA implementa esta interfaz.) Ver SVGPolygonElement, SVGAnimatedPoints, SVGPointList y SVGPoint.

Sin embargo, el uso de estas interfaces SVG DOM (al menos para mí en Batik, en el que hago la mayoría de mis cosas SVG) a menudo no es más rápido que simplemente actualizar el atributo con manipulación de cadenas.