[javascript] jQuery SVG, 왜 클래스를 추가 할 수 없습니까?

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.');
});



답변

2016 수정 : 다음 두 가지 답변을 읽으십시오.

  • JQuery 3은 근본적인 문제를 해결
  • 바닐라 JS : element.classList.add('newclass')최신 브라우저에서 작동

JQuery (3 미만)는 SVG에 클래스를 추가 할 수 없습니다.

.attr() SVG와 함께 작동하므로 jQuery에 의존하려면 다음을 수행하십시오.

// Instead of .addClass("newclass")
$("#item").attr("class", "oldclass newclass");
// Instead of .removeClass("newclass")
$("#item").attr("class", "oldclass");

그리고 jQuery에 의존하고 싶지 않으면 :

var element = document.getElementById("item");
// Instead of .addClass("newclass")
element.setAttribute("class", "oldclass newclass");
// Instead of .removeClass("newclass")
element.setAttribute("class", "oldclass");


답변

DOM API에는 HTML 및 SVG 요소 모두에 대해 작동하는 element.classList 가 있습니다 . jQuery SVG 플러그인이나 jQuery가 필요하지 않습니다.

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


답변

jQuery 3에는이 문제가 없습니다

jQuery 3.0 개정판 에 나열된 변경 사항 중 하나 는 다음과 같습니다.

SVG 클래스 조작 추가 ( # 2199 , 20aaed3 )

이 문제에 대한 한 가지 해결책은 jQuery 3으로 업그레이드하는 것입니다.

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;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>

<svg>
    <circle cx="50" cy="50" r="25" />
</svg>


문제 :

jQuery 클래스 조작 함수가 SVG 요소에서 작동하지 않는 이유는 3.0 이전의 jQuery 버전 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 {
    width: 200px;
    height: 50px;
    background: blue;
}
<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"}

SVGAnimatedStringjQuery와 같이 해당 객체를 문자열로 캐스트 [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 요소인지 여부를 감지하고, 가능한 경우 해당 요소가 SVG 요소로 넘어 가기 전에 객체 의 baseVal속성을 사용합니다 SVGAnimatedString.class 합니다.

문제에 대한 jQuery의 역사적 입장 :

jQuery는 현재이 문제를 수정 안 함 페이지 에 나열 합니다. 관련 부품은 다음과 같습니다.

SVG / VML 또는 네임 스페이스 요소 버그

jQuery는 주로 HTML DOM 용 라이브러리이므로 SVG / VML 문서 또는 네임 스페이스 요소와 관련된 대부분의 문제는 범위를 벗어납니다. SVG에서 버블 링되는 이벤트와 같이 HTML 문서에 “블리드”되는 문제를 해결하려고합니다.

분명히 jQuery는 jQuery 코어 범위 밖에서 완전한 SVG 지원을 고려했으며 플러그인에 더 적합했습니다.


답변

동적 클래스가 있거나 어떤 클래스를 이미 적용 할 수 있는지 모르는 경우이 방법이 최선의 방법이라고 생각합니다.

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

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


답변

위의 답변을 바탕으로 다음 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;
};


답변

로드 후이 jquery.svg.js파일을로드해야합니다.http://keith-wood.name/js/jquery.svgdom.js ..

출처 : http://keith-wood.name/svg.html#dom

실례 : http://jsfiddle.net/74RbC/99/


답변

누락 된 프로토 타입 생성자를 모든 SVG 노드에 추가하십시오.

SVGElement.prototype.hasClass = function (className) {
  return new RegExp('(\\s|^)' + className + '(\\s|$)').test(this.getAttribute('class'));
};

SVGElement.prototype.addClass = function (className) {
  if (!this.hasClass(className)) {
    this.setAttribute('class', this.getAttribute('class') + ' ' + className);
  }
};

SVGElement.prototype.removeClass = function (className) {
  var removedClass = this.getAttribute('class').replace(new RegExp('(\\s|^)' + className + '(\\s|$)', 'g'), '$2');
  if (this.hasClass(className)) {
    this.setAttribute('class', removedClass);
  }
};

그런 다음 jQuery를 요구하지 않고이 방법으로 사용할 수 있습니다.

this.addClass('clicked');

this.removeClass('clicked');

모든 크레딧은 Todd Moto 로갑니다 .