我使用jQuery SVG。我不能向对象添加或删除类。有人知道我的错误吗?

SVG:

<rect class="jimmy" id="p5" x="200" y="200" width="100" height="100" />

jQuery不会添加类:

$(".jimmy").click(function() {
    $(this).addClass("clicked");
});

我知道SVG和jQuery一起工作很好,因为我可以瞄准对象,并在点击时发出警报:

$(".jimmy").click(function() {
    alert('Handler for .click() called.');
});

当前回答

基于以上答案,我创建了以下API

/*
 * .addClassSVG(className)
 * Adds the specified class(es) to each of the set of matched SVG elements.
 */
$.fn.addClassSVG = function(className){
    $(this).attr('class', function(index, existingClassNames) {
        return ((existingClassNames !== undefined) ? (existingClassNames + ' ') : '') + className;
    });
    return this;
};

/*
 * .removeClassSVG(className)
 * Removes the specified class to each of the set of matched SVG elements.
 */
$.fn.removeClassSVG = function(className){
    $(this).attr('class', function(index, existingClassNames) {
        var re = new RegExp('\\b' + className + '\\b', 'g');
        return existingClassNames.replace(re, '');
    });
    return this;
};

其他回答

如果你有动态类或者不知道什么类可以被应用,那么我认为这个方法是最好的方法:

// addClass
$('path').attr('class', function(index, classNames) {
    return classNames + ' class-name';
});

// removeClass
$('path').attr('class', function(index, classNames) {
    return classNames.replace('class-name', '');
});

这里是我的相当不优雅,但工作的代码,处理以下问题(没有任何依赖):

IE中<svg>元素上不存在classList className不代表IE中<svg>元素上的class属性 旧IE的破碎的getAttribute()和setAttribute()实现

它尽可能使用classList。

代码:

var classNameContainsClass = function(fullClassName, className) {
    return !!fullClassName &&
           new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(fullClassName);
};

var hasClass = function(el, className) {
    if (el.nodeType !== 1) {
        return false;
    }
    if (typeof el.classList == "object") {
        return (el.nodeType == 1) && el.classList.contains(className);
    } else {
        var classNameSupported = (typeof el.className == "string");
        var elClass = classNameSupported ? el.className : el.getAttribute("class");
        return classNameContainsClass(elClass, className);
    }
};

var addClass = function(el, className) {
    if (el.nodeType !== 1) {
        return;
    }
    if (typeof el.classList == "object") {
        el.classList.add(className);
    } else {
        var classNameSupported = (typeof el.className == "string");
        var elClass = classNameSupported ?
            el.className : el.getAttribute("class");
        if (elClass) {
            if (!classNameContainsClass(elClass, className)) {
                elClass += " " + className;
            }
        } else {
            elClass = className;
        }
        if (classNameSupported) {
            el.className = elClass;
        } else {
            el.setAttribute("class", elClass);
        }
    }
};

var removeClass = (function() {
    function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) {
        return (whiteSpaceBefore && whiteSpaceAfter) ? " " : "";
    }

    return function(el, className) {
        if (el.nodeType !== 1) {
            return;
        }
        if (typeof el.classList == "object") {
            el.classList.remove(className);
        } else {
            var classNameSupported = (typeof el.className == "string");
            var elClass = classNameSupported ?
                el.className : el.getAttribute("class");
            elClass = elClass.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer);
            if (classNameSupported) {
                el.className = elClass;
            } else {
                el.setAttribute("class", elClass);
            }
        }
    }; //added semicolon here
})();

使用示例:

var el = document.getElementById("someId");
if (hasClass(el, "someClass")) {
    removeClass(el, "someClass");
}
addClass(el, "someOtherClass");

jQuery 3没有这个问题

jQuery 3.0版本中列出的一个变化是:

添加SVG类操作(#2199,20aaed3)

这个问题的一个解决方案是升级到jQuery 3。它很有效:

Var翻转= true; setInterval(函数(){ //可以使用toggleClass,但要演示addClass。 If(翻转){ $ (svg圆).addClass(“绿色”); } 其他{ $ (svg圆).removeClass(“绿色”); } 翻转= ! }, 1000); SVG圆{ 填充:红色; 中风:黑色; 笔划宽度:5; } svg圆。绿色{ 填充:绿色; } < script src = " https://code.jquery.com/jquery-3.0.0.min.js " > < /脚本> svg < > <circle cx="50" cy="50" r="25" /> < / svg >


存在的问题:

jQuery类操作函数不能与SVG元素一起工作的原因是jQuery 3.0之前的版本对这些函数使用className属性。

摘自jQuery attributes/classes.js:

cur = elem.nodeType === 1 && ( elem.className ?
    ( " " + elem.className + " " ).replace( rclass, " " ) :
    " "
);

这与HTML元素的行为一致,但对于SVG元素,className略有不同。对于SVG元素,className不是字符串,而是SVGAnimatedString的实例。

考虑下面的代码:

var test_div = document.getElementById('test-div'); var test_svg = document.getElementById('test-svg'); console.log (test_div.className); console.log (test_svg.className); # test-div { 宽度:200 px; 高度:50 px; 背景:蓝色; } <div class="test div" id="test-div"></div> <svg width="200" height="50" viewBox="0 0 200 50"> <rect width="200" height="50" fill="green" class="test svg" id="test-svg" /> . < / svg >

如果运行这段代码,您将在开发人员控制台中看到如下内容。

test div
SVGAnimatedString { baseVal="test svg",  animVal="test svg"}

如果我们要将SVGAnimatedString对象转换为jQuery所做的字符串,我们将有[object SVGAnimatedString],这是jQuery失败的地方。

jQuery SVG插件如何处理这个:

jQuery SVG插件通过修补相关函数来添加SVG支持,从而解决了这个问题。

摘自jQuery SVG jQuery .svgdom.js

function getClassNames(elem) {
    return (!$.svg.isSVGElem(elem) ? elem.className :
        (elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}

这个函数将检测一个元素是否是SVG元素,如果是,它将使用SVGAnimatedString对象的baseVal属性(如果可用),然后返回到class属性。

jQuery在这个问题上的历史立场:

jQuery目前在Won 't Fix页面上列出了这个问题。以下是相关部分。

SVG/VML或命名空间元素bug jQuery主要是HTML DOM的库,因此大多数与SVG/VML文档或名称空间元素相关的问题都不在讨论范围之内。我们确实尝试解决“渗透”到HTML文档的问题,比如从SVG冒出来的事件。

显然,jQuery认为完全支持SVG超出了jQuery核心的范围,更适合插件。

或者,当JQ在某个地方出现问题时,只使用老派的DOM方法。

var myElement = $('#my_element')[0];
var myElClass = myElement.getAttribute('class').split(/\s+/g);
//splits class into an array based on 1+ white space characters

myElClass.push('new_class');

myElement.setAttribute('class', myElClass.join(' '));

//$(myElement) to return to JQ wrapper-land

了解DOM人。即使是在2016年的框架狂欢中,它也经常有所帮助。此外,如果您曾经听到有人将DOM与汇编进行比较,请替我踢他们一脚。

我使用Snap.svg向SVG添加一个类。

var jimmy = Snap(" .jimmy ")

jimmy.addClass("exampleClass");

http://snapsvg.io/docs/#Element.addClass