私は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がうまく連携していることを私は知っています。なぜなら、私はcanオブジェクトをターゲットにし、クリックされると警告を発するからです。
$(".jimmy").click(function() {
alert('Handler for .click() called.');
});
2016年の編集:次の2つの答えを読んでください。
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には element.classList があり、これはHTMLとSVGの両方の要素に対して機能します。 jQuery SVGプラグインやjQueryさえも必要ありません。
$(".jimmy").click(function() {
this.classList.add("clicked");
});
jQuery 3.0のリビジョン に記載されている変更の1つは次のとおりです。
この問題に対する1つの解決策は、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
プロパティを使用しているためです。
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"}
そのSVGAnimatedString
オブジェクトをjQueryのように文字列にキャストすると、[object SVGAnimatedString]
ができます。これがjQueryの失敗です。
JQuery SVGプラグインは、SVGサポートを追加するために関連機能にパッチを適用することによってこれを回避します。
jquery.svgdom.js
:function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
この関数は、要素がSVG要素であるかどうかを検出し、存在する場合はbaseVal
オブジェクトにSVGAnimatedString
プロパティがあればそれを使用してからclass
属性にフォールバックします。
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
。
足りないプロトタイプコンストラクタをすべての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 になります。
jQuery 2.2 and 1.12 Released 投稿には以下の引用が含まれています。
JQueryはHTMLライブラリですが、SVG要素のクラスサポートが役立つことに同意しました。ユーザーは。addClass()、。removeClass()、を呼び出せるようになります。 SVGのtoggleClass()、および。hasClass()メソッド。 jQuerynowは、classNameプロパティではなくclass属性を変更します。これにより、クラスメソッドは一般的なXML文書でも使用可能になります。 SVGでは他にも多くのことがうまくいかないことに注意してください。クラスの操作以外に何か必要な場合は、SVG専用のライブラリを使用することをお勧めします。
それはテストします:
その小さな四角をクリックすると、class
属性が追加/削除されるため、色が変わります。
$("#x").click(function() {
if ( $(this).hasClass("clicked") ) {
$(this).removeClass("clicked");
} else {
$(this).addClass("clicked");
}
});
.clicked {
fill: red !important;
}
<html>
<head>
<script src="https://code.jquery.com/jquery-2.2.0.js"></script>
</head>
<body>
<svg width="80" height="80">
<rect id="x" width="80" height="80" style="fill:rgb(0,0,255)" />
</svg>
</body>
</html>
jQueryはSVG要素のクラスをサポートしません。要素を直接$(el).get(0)
と取得し、classList
とadd / remove
を使用することができます。一番上のSVG要素は実際には通常のDOMオブジェクトであり、jQueryの他のすべての要素と同じように使用できるという点で、これにもトリックがあります。私のプロジェクトでは、私が必要としていたものの世話をするためにこれを作成しましたが、 Mozilla Developer Network で提供されている文書には代替として使用できるシムがあります。
function addRemoveClass(jqEl, className, addOrRemove)
{
var classAttr = jqEl.attr('class');
if (!addOrRemove) {
classAttr = classAttr.replace(new RegExp('\\s?' + className), '');
jqEl.attr('class', classAttr);
} else {
classAttr = classAttr + (classAttr.length === 0 ? '' : ' ') + className;
jqEl.attr('class', classAttr);
}
}
もっと難しいのは、代わりにD3.jsをセレクタエンジンとして使うことです。私のプロジェクトはそれで構築されたチャートを持っているので、それは私のアプリの範囲にもあります。 D3は、Vanilla DOM要素とSVG要素のクラス属性を正しく修正します。この場合だけD3を追加するのはやり過ぎです。
d3.select(el).classed('myclass', true);
これは私のやや洗練されていないが実用的なコードで、以下の問題を扱います(依存関係はありません)。
<svg>
要素にclassList
が存在しません<svg>
要素のclassName
属性がclass
属性を表していません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");
Snap.svgを使ってSVGにクラスを追加します。
var jimmy = Snap(" .jimmy ")
jimmy.addClass("exampleClass");
1つの回避策は、svg要素のコンテナーにaddClassを追加することです。
$('.svg-container').addClass('svg-red');
.svg-red svg circle{
fill: #ED3F32;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="svg-container">
<svg height="40" width="40">
<circle cx="20" cy="20" r="20"/>
</svg>
</div>
上記の答え、特にSagar Galaの影響を受けて、私はこれを作成しました API 。 jqueryのバージョンをアップグレードしたくない場合やアップグレードできない場合は、これを使用できます。
私は自分のプロジェクトでこれを書きました、そしてそれはうまくいきます...おそらく;)
$.fn.addSvgClass = function(className) {
var attr
this.each(function() {
attr = $(this).attr('class')
if(attr.indexOf(className) < 0) {
$(this).attr('class', attr+' '+className+ ' ')
}
})
};
$.fn.removeSvgClass = function(className) {
var attr
this.each(function() {
attr = $(this).attr('class')
attr = attr.replace(className , ' ')
$(this).attr('class' , attr)
})
};
例
$('path').addSvgClass('fillWithOrange')
$('path').removeSvgClass('fillWithOrange')