jQuery 选择器 + SVG 不兼容?

IT技术 javascript jquery xhtml jquery-selectors svg
2021-01-21 08:37:14

我一直在处理带有内联 SVG 和 javascript 动画的 HTML5 文档。

当用户点击任何地方时,我希望弹出一个框,当用户点击某个不是框的地方时,我希望框消失。这意味着我不能使用$(window).click(),它有效。

我已经尝试通过给它们类名和使用来选择顶部的 SVG $(".svgclassname").click(),但这似乎不起作用。用 选择单个的也不行$("#svgname").click()

问题是什么?

(当我用 替换$(".eyesvg")$(window),当用户单击窗口中的任意位置时,光标附近会出现一个蓝色框。)

3个回答

发生这种情况是因为 SVG DOM 规范与 HTML DOM 有很大不同。

SVG DOM 是一种不同的方言,有些属性具有相同的名称但含义不同。例如,要获取 svg 元素的 className,请使用:

svg.className.baseVal

受此影响的属性是

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

这些 Animated 属性是结构,具有与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 对象创建了一个包装器,使它们看起来像 jQuery 的 HTML DOM。我已经将它与 jQuery-UI 一起使用,使我的 SVG 元素可放置。

HTML 和 SVG 之间缺乏 DOM 互操作性是一场彻头彻尾的灾难。所有为 HTML 编写的甜蜜实用程序库都必须为 SVG 重新发明。

这看起来不错 - 但它应该如何使用?
2021-03-25 08:37:14
嘿,Aleksander,感谢您的建议!该代码段让我们走得很远,但由于在将原型继承直接与 SVG DOM 元素一起使用时引发的错误而无法在 Firefox 15 中工作。我们已经对其进行了修改以在 Firefox 中工作并成功使用它。代码在这里:github.com/RedBrainLabs/jquery.wrap-svg
2021-04-04 08:37:14
刚刚在 Safari 8.0 中加载脚本时出现错误:“语法错误:函数语句必须有一个名称。” (svg.js,第 1 行)。我将脚本放在一个单独的 js 文件 svg.js 中,并尝试在 jQuery 文件之前和之后加载它。在这两种情况下相同的错误。
2021-04-13 08:37:14

你可以使用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>

有时我不明白……但实际上它不适用于类选择器。如果您使用 id $("#mysvg") 或元素 $("svg") 它确实有效!奇怪的....

它仅在您将 onClick 脚本从标题移动到 svg 元素之后的正文时才有效!jquery只能在绑定之前声明元素时绑定onclick。

请注意,您可以使用$('*[class~="eyesvg"]')属性包含 word selector按类选择 SVG 元素
2021-03-25 08:37:14
啊哈!这非常有效。尽管 jQuery 的类选择器存在问题,但我确信我只能选择多个 id。谢谢!
2021-04-12 08:37:14