Esto ocurre porque la especificación SVG DOM difiere mucho de HTML DOM.
SVG DOM es un dialecto diferente, y algunas propiedades tienen los mismos nombres pero significan cosas diferentes. Por ejemplo, para obtener el className de un elemento SVG, que utilice:
svg.className.baseVal
Los properites afectados por esto son
className is SVGAnimatedString
height,width, x, y, offsetWidth, offsetHeight are SVGAnimatedLength
Estas propiedades son animados estructuras, con baseVal
sosteniendo el mismo valor que había encontrar en HTML DOM y animatedVal
sosteniendo No estoy seguro de qué.
SVG DOM también le faltan algunas propiedades de las que dependen las bibliotecas, como innerHTML
.
Esto rompe jQuery de muchas maneras, cualquier cosa que dependa de las propiedades anteriores falla.
En general, SV SV DOM y HTML DOM no se mezclan muy bien. Trabajan juntos lo suficiente para atraerte, y luego las cosas se rompen silenciosamente, y otro ángel pierde sus alas.
me escribió una pequeña extensión de jQuery que envuelve elementos SVG para que se vean más como HTML DOM
(function (jQuery){
function svgWrapper(el) {
this._svgEl = el;
this.__proto__ = el;
Object.defineProperty(this, "className", {
get: function(){ return this._svgEl.className.baseVal; },
set: function(value){ this._svgEl.className.baseVal = value; }
});
Object.defineProperty(this, "width", {
get: function(){ return this._svgEl.width.baseVal.value; },
set: function(value){ this._svgEl.width.baseVal.value = value; }
});
Object.defineProperty(this, "height", {
get: function(){ return this._svgEl.height.baseVal.value; },
set: function(value){ this._svgEl.height.baseVal.value = value; }
});
Object.defineProperty(this, "x", {
get: function(){ return this._svgEl.x.baseVal.value; },
set: function(value){ this._svgEl.x.baseVal.value = value; }
});
Object.defineProperty(this, "y", {
get: function(){ return this._svgEl.y.baseVal.value; },
set: function(value){ this._svgEl.y.baseVal.value = value; }
});
Object.defineProperty(this, "offsetWidth", {
get: function(){ return this._svgEl.width.baseVal.value; },
set: function(value){ this._svgEl.width.baseVal.value = value; }
});
Object.defineProperty(this, "offsetHeight", {
get: function(){ return this._svgEl.height.baseVal.value; },
set: function(value){ this._svgEl.height.baseVal.value = value; }
});
};
jQuery.fn.wrapSvg = function() {
return this.map(function(i, el) {
if (el.namespaceURI == "http://www.w3.org/2000/svg" && !('_svgEl' in el))
return new svgWrapper(el);
else
return el;
});
};
})(window.jQuery);
Se crea una cobertura de los objetos SVG que hace que se vean como HTML DOM para jQuery. Lo he usado con jQuery-UI para hacer que mis elementos SVG sean desplegables.
La falta de interoperabilidad DOM entre HTML y SVG es un desastre total. Todas las bibliotecas de utilidad dulce escritas para HTML deben reinventarse para SVG.
¡Hola Aleksander, gracias por esta sugerencia! El fragmento nos llevó bastante lejos, pero no funcionó en Firefox 15 debido a un error al usar la herencia de prototipos directamente con un elemento SVG DOM. Lo hemos modificado para que funcione en Firefox y lo estamos utilizando con éxito. El código está aquí: http://github.com/RedBrainLabs/jquery.wrap-svg –
Simplemente cargando la secuencia de comandos en Safari 8.0 Obtuve un error: "SyntaxError: las instrucciones de la función deben tener un nombre". (svg.js, línea 1). Puse el script en un archivo js separado, svg.js, y traté de cargarlo antes y después del archivo jQuery. Mismo error en ambos casos. –
Esto se ve genial, pero ¿cómo se supone que debe usarse? – kris