2010-07-20 37 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>