2010-07-20 34 views
34

我一直在用HTML5文檔處理內聯SVG和javascript動畫。jQuery Selector + SVG不兼容?

我想在用戶點擊任何地方時彈出一個框,並且當用戶單擊某個不是框的地方時,我希望框消失。這意味着我不能使用$(window).click(),這是有效的。

我試着選擇SVGs給他們上課名稱和使用$(".svgclassname").click(),但這似乎並不奏效。使用$("#svgname").click()也不會選擇單個的。

什麼問題?

(當我與$(window)取代$(".eyesvg"),當用戶在窗口中點擊任意位置出現藍框光標附近。)

回答

64

發生這種情況是因爲SVG DOM規範與HTML DOM差別很大。

SVG DOM是一種不同的方言,一些屬性具有相同的名稱,但意味着不同的東西。例如,爲了得到一個SVG元素的類名,您可以使用:

svg.className.baseVal 

受此影響的性質在被

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

這些動畫屬性結構,與baseVal抱着你會相同的值發現在HTML DOM和animatedVal持有我不知道是什麼。

SVG DOM還缺少一些屬性庫依賴的屬性,例如innerHTML

這在很多方面都會打破jQuery,任何依賴上述屬性的東西都會失敗。

一般來說,SVG DOM和HTML DOM不會很好地混合。他們一起工作就足以引誘你,然後事情就會平靜下來,另一位天使失去了翅膀。

我寫了一個小的jQuery擴展包SVG元素,使它們看起來更象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); 

它創建圍繞SVG對象,使它們看起來像HTML DOM jQuery的包裝。我用它與jQuery-UI一起使我的SVG元素可以放置。

HTML與SVG之間缺乏DOM互操作性是一場徹底的災難。爲HTML編寫的所有甜蜜實用程序庫都必須重新創建SVG。

+7

嘿那裏Aleksander,謝謝你的建議!這段代碼讓我們非常滿意,但在Firefox 15中無法正常工作,原因是直接對SVG DOM元素使用原型繼承時出現錯誤。我們已將其修改爲可在Firefox中使用併成功使用它。代碼在這裏:http://github.com/RedBrainLabs/jquery.wrap-svg – 2012-09-07 21:18:21

+0

只需在Safari 8.0中加載腳本,我得到一個錯誤:「SyntaxError:函數語句必須有一個名稱。」 (svg.js,第1行)。我已經把腳本放在一個單獨的js文件svg.js中,並嘗試在jQuery文件之前和之後加載它。兩種情況都有同樣的錯誤。 – 2014-07-28 11:35:40

+0

這看起來不錯 - 但它應該如何使用? – kris 2017-07-05 01:38:11

3

有時我不明白這一點......但實際上這是行不通的與類選擇器。如果你使用id $(「#mysvg」)或元素$(「svg」),它確實可行!奇怪的......

它只適用於當您將onClick腳本從標題移動到svg元素之後的主體時!當元素在綁定之前聲明時,jquery只能綁定onclick。

+0

啊哈!這非常有效。儘管jQuery與類選擇器有關,但我確信我只能選擇多個id。謝謝! – thure 2010-07-21 14:55:22

+9

請注意,您可以通過使用'$('* [class〜=「eyesvg」]')來選擇SVG元素([屬性包含單詞選擇器](http://api.jquery.com/attribute-contains -word選擇器/))。 – Phrogz 2011-05-03 20:26:35

3

u可以使用jquery-svg插件,像一個魅力:

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