jQuery SVG, why can't I addClass?

前端 未结 15 2201
失恋的感觉
失恋的感觉 2020-11-22 02:25

I am using jQuery SVG. I can\'t add or remove a class to an object. Anyone know my mistake?

The SVG:



        
15条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-22 02:44

    jQuery 3 does not have this problem

    One of the changes listed on the jQuery 3.0 revisions is:

    add SVG class manipulation (#2199, 20aaed3)

    One solution for this issue would be to upgrade to jQuery 3. It works great:

    var flip = true;
    setInterval(function() {
        // Could use toggleClass, but demonstrating addClass.
        if (flip) {
            $('svg circle').addClass('green');
        }
        else {
            $('svg circle').removeClass('green');
        }
        flip = !flip;
    }, 1000);
    svg circle {
        fill: red;
        stroke: black;
        stroke-width: 5;
    }
    svg circle.green {
        fill: green;
    }
    
    
    
        
    


    The Problem:

    The reason the jQuery class manipulation functions do not work with the SVG elements is because jQuery versions prior to 3.0 use the className property for these functions.

    Excerpt from jQuery attributes/classes.js:

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

    This behaves as expected for HTML elements, but for SVG elements className is a little different. For an SVG element, className is not a string, but an instance of SVGAnimatedString.

    Consider the following code:

    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 {
        width: 200px;
        height: 50px;
        background: blue;
    }

    If you run this code you will see something like the following in your developer console.

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

    If we were to cast that SVGAnimatedString object to a string as jQuery does, we would have [object SVGAnimatedString], which is where jQuery fails.

    How the jQuery SVG plugin handles this:

    The jQuery SVG plugin works around this by patching the relevant functions to add SVG support.

    Excerpt from jQuery SVG jquery.svgdom.js:

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

    This function will detect if an element is an SVG element, and if it is it will use the baseVal property of the SVGAnimatedString object if available, before falling back on the class attribute.

    jQuery's historical stance on the issue:

    jQuery currently lists this issue on their Won’t Fix page. Here is the relevant parts.

    SVG/VML or Namespaced Elements Bugs

    jQuery is primarily a library for the HTML DOM, so most problems related to SVG/VML documents or namespaced elements are out of scope. We do try to address problems that "bleed through" to HTML documents, such as events that bubble out of SVG.

    Evidently jQuery considered full SVG support outside the scope of the jQuery core, and better suited for plugins.

提交回复
热议问题