38 votes

jQuery Selector - SVG Incompatible?

J'ai travaillé avec un document HTML5 avec inline SVG et javascript animation.

J'aimerais avoir une boîte de pop-up lorsque l'utilisateur clique n'importe où, et j'aimerais la boîte à disparaître lorsque l'utilisateur clique quelque part qui n'est pas de la case. Cela signifie que je ne peux pas utiliser $(window).click(), ce qui fonctionne.

J'ai essayé en sélectionnant le SVGs sur le dessus, en leur donnant des noms de classe et à l'aide de $(".svgclassname").click(), mais cela ne semble pas fonctionner. Ni ne choisis avec $("#svgname").click().

Quel est le problème?

Vous pouvez voir la page en utilisant le code source que j'ai décrit ici: index.xhtml

(Lorsque je remplace $(".eyesvg") avec $(window), une boîte bleue apparaît à proximité du curseur lorsque l'utilisateur clique n'importe où dans la fenêtre.)

68voto

Aleksandar Totic Points 1605

Cela se produit parce que le SVG DOM spec diffère beaucoup de DOM HTML.

SVG DOM est un autre dialecte, et certaines propriétés ont les mêmes noms, mais de signifier des choses différentes. Par exemple, pour obtenir le nom de classe d'un élément svg, vous utilisez:

svg.className.baseVal

Le properites concernés par cela

className is SVGAnimatedString
height,width, x, y, offsetWidth, offsetHeight are SVGAnimatedLength

Ces propriétés Animées sont les structures, avec baseVal le maintien de la même valeur, que vous pouvez trouver dans les DOM HTML et animatedVal la tenue, je ne suis pas sûr de ce que.

SVG DOM est également absente de certains properies les bibliothèques dépendent, tels que innerHTML.

Cela rompt avec jQuery dans beaucoup de façons, tout ce qui dépend des propriétés ci-dessus échoue.

En général, SVG DOM et DOM HTML ne mélangent pas très bien. Ils travaillent ensemble, juste assez pour vous attirer dans, et ensuite les choses se casser tranquillement, et un autre ange perd ses ailes.

J'ai écrit un peu de jQuery extension qui enveloppe les éléments SVG pour les rendre plus comme DOM HTML

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);

Il crée un wrapper autour de SVG objets qui les fait ressembler à DOM HTML pour jQuery. Je l'ai utilisé avec jQuery UI pour faire ma éléments SVG droppable.

Le manque de DOM interopérabilité entre HTML et SVG est un désastre total. Tous les sweet utilité des bibliothèques écrites en HTML doivent être réinventées pour SVG.

4voto

räph Points 1858

parfois je ne comprends pas ... mais en fait, il ne fonctionne pas avec le sélecteur de classe. Si vous utilisez l'id $("#mysvg") ou l'élément $("svg") il fonctionne! Étrange....

Et il ne fonctionne que lorsque vous déplacez le script onClick de l'en-tête au corps après l'élément svg! jquery ne peut lier l'onclick que lorsque l'élément est déclaré avant la liaison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X