2010-07-20 18 views
34

Pracowałem z dokumentem HTML5 z wbudowaną animacją SVG i javascript.jQuery Selector + SVG jest niezgodny?

Chciałbym mieć okienko wyskakujące, gdy użytkownik kliknie w dowolnym miejscu, a chciałbym, aby okno zniknęło, gdy użytkownik kliknie gdzieś, co nie jest tym pudełkiem. Oznacza to, że nie mogę użyć $(window).click(), która działa.

Próbowałem wybrać SVG na górze, nadając im nazwy klas i używając $(".svgclassname").click(), ale to nie działa. Nie wybiera też pojedynczych z $("#svgname").click().

Na czym polega problem?

(podczas wymiany $(".eyesvg") z $(window) pojawi się niebieskie pole obok kursora, gdy użytkownik kliknie w dowolnym miejscu okna.)

Odpowiedz

64

Dzieje się tak, ponieważ specyfikacja SVG DOM różni się znacznie od HTML DOM.

SVG DOM to inny dialekt, a niektóre właściwości mają te same nazwy, ale oznaczają różne rzeczy. Na przykład, aby uzyskać className elementu SVG, możesz użyć:

svg.className.baseVal 

W properites dotknięte przez to są

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

Te animowane właściwości są kodowanym, z baseVal posiadających taką samą wartość, którą znaleźć w HTML DOM i animatedVal trzymając nie jestem pewien co.

W SVG DOM również brakuje niektórych bibliotek właściwości, takich jak innerHTML.

To łamie jQuery na wiele sposobów, wszystko, co zależy od powyższych właściwości, zawodzi.

Ogólnie SVG DOM i HTML DOM nie mieszają się bardzo dobrze. Pracują razem na tyle, by cię zwabić, a potem wszystko cichnie, a inny anioł traci skrzydła.

pisałem trochę rozszerzenie jQuery, która otacza elementy SVG, aby wyglądały bardziej jak 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); 

Tworzy otoki wokół obiektów SVG, który sprawia, że ​​wyglądają jak HTML DOM do jQuery. Używałem go z jQuery-UI do zrzucania elementów SVG.

Brak interoperacyjności DOM między HTML a SVG jest całkowitą katastrofą. Wszystkie słodkie biblioteki narzędziowe napisane dla HTML muszą zostać ponownie utworzone dla SVG.

+7

Hej, Aleksander, dzięki za tę sugestię! Fragment dostał nas dość daleko, ale nie działał w Firefoksie 15 z powodu błędu podniesionego podczas korzystania z prototypowego dziedziczenia bezpośrednio z elementem SVG DOM. Zmodyfikowaliśmy go tak, aby działał w Firefoksie i używa go z powodzeniem. Kod znajduje się tutaj: http://github.com/RedBrainLabs/jquery.wrap-svg –

+0

Po prostu ładowanie skryptu w Safari 8.0 Pojawił się błąd: "SyntaxError: Instrukcje funkcji muszą mieć nazwę." (svg.js, wiersz 1). Umieściłem skrypt w oddzielnym pliku js, svg.js i próbowałem ładować go przed i po pliku jQuery. Ten sam błąd w obu przypadkach. –

+0

To wygląda świetnie - ale jak to ma być użyte? – kris

3

czasami nie rozumiem ... ale w rzeczywistości to nie działa z selektorem klasy. Jeśli użyjesz id $ ("# mysvg") lub elementu $ ("svg"), to działa! Dziwne ...

Działa to tylko po przeniesieniu skryptu onClick z nagłówka do treści po elemencie svg! jquery może tylko powiązać onclick, gdy element jest zadeklarowany przed powiązaniem.

+0

Aha! To działa bajecznie.Pomimo problemu z jQuery z selektorem klasy, jestem pewien, że będę mógł wybrać wiele identyfikatorów. Dzięki! – thure

+9

Pamiętaj, że możesz wybrać elementy SVG według klas, używając '$ ('* [class ~ =" eyesvg "]')' (atrybut [zawiera selektor słów] (http://api.jquery.com/attribute-contains) -word-selector /)). – Phrogz

3

u mogą korzystać jquery-svg wtyczki, jak czar:

<script> 
    //get svg object, like a jquery object 
    var svg = $("#cars").getSVG(); 
    //use jquery functions to do some thing 
    svg.find("g path:first-child()").attr('fill', color); 
</script>