こんにちは私は多くの小さなsvgグラフィック(市地区)で構成されるsvg/jsマップに取り組んでいます。すべてのグラフィックを独自のファイルに入れるので、メインのsvgファイルは引き続き保守可能で、肥大化しません。
別のsvgから外部svgファイルを正しく参照するにはどうすればよいですか?
期待される結果:1.svgをブラウザーで開くと、青い四角形が表示されます。動作方法: w3c:要素を使用
これが私が試したものです:1.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="style.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG- 20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
<use xlink:href="another.svg#rectangle"/>
</svg>
another.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG- 20010904/DTD/svg10.dtd">
<svg id="rectangle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
<rect class="blue" x="558.5" y="570" width="5" height="5" />
</svg>
style.css
.blue { fill: blue; }
結果:
注:画像要素で試しましたが、スタイルシートでは機能しませんでした。つまり、青い長方形ではなく黒い長方形が表示されました。
重要:別のSVGを参照する場合およびに正式なドキュメント構造の一部としてSVGを参照している場合、 AJAXを使用 を使用してこれを行うことができます。
これは元の質問に答えますが、SVGで外部SVGファイルを参照するという問題にも広義で回答しようとします。
6年後、ChromeとSafariでは、外部SVGファイルの参照/ロードはまだ許可されていません。
これが、Firefoxでは<use xlink:href="another.svg#rectangle" class="blue"/>
が機能するが、WebKitブラウザーでは機能しない理由です。
プロジェクトに余裕がある場合は、すべてのSVGファイルを1つの親HTMLまたはSVGファイルに配置するだけです。これにより、3つのブラウザすべてで機能します。
しかし、それは実際には外部的なものではありません。
キャッシングのメリットを活用し、自分自身の繰り返しを避けるために、繰り返し可能なSVGコンテンツを外部ファイルに保持したいと考えています。
スタイルと定義を1つのSVGファイルに保存し、SVGジオメトリを他のファイルに保存し、JavaScriptを介して前者を後者からロードするだけです。
何を使用できるようにするかを定義します。 styles-and-defs.svg
:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css" >
<![CDATA[
.blue { fill: blue; }
]]>
</style>
<defs>
<rect id="rectangle" class="blue" width="50" height="50" />
</defs>
</svg>
上記で作成したジオメトリを使用して、その定義をロードします。 parent.svg
:
<svg version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="420" height="120">
<use xlink:href="#rectangle" x="10" y="10" />
<script><![CDATA[
/** When the document is ready, this self-executing function will be run. **/
(function() {
var ajax = new XMLHttpRequest();
ajax.open("GET", "styles-and-defs.svg", true);
ajax.send();
/**
* Append the external SVG to this very SVG.
*
* Notice the use of an SVG selector on the document derived from the AJAX result.
* This is because the full document cannot be included directly into the SVG.
* Trying to include to do so would result in:
* `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
* `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
*/
ajax.onload = function(e) {
var parser = new DOMParser();
var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
document.getElementsByTagName('svg')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
}
})(); /* END (anonymous function) */
]]></script>
</svg>
これはOPに応答します。
純粋なSVGと同じ基本的なアプローチ:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Load external SVG (HTML)
</title>
<meta name="author" content="Fabien Snauwaert">
</head>
<body>
<svg version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="420" height="120">
<use xlink:href="#rectangle" x="10" y="10" />
</svg>
<script>
/** When the document is ready, this self-executing function will be run. **/
(function() {
var ajax = new XMLHttpRequest();
ajax.open("GET", "styles-and-defs.svg", true);
ajax.send();
/**
* Append the external SVG to this very SVG.
*
* Notice the use of an SVG selector on the document derived from the AJAX result.
* This is because the full cannot be included directly into the SVG.
* Trying to include to do so would result in:
* `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
* `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
*/
ajax.onload = function(e) {
var parser = new DOMParser();
var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
document.getElementsByTagName('body')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
}
})(); /* END (anonymous function) */
</script>
</body>
</html>
もちろん、代わりにjQuery(または優れた D3.js )を使用してファイルをロードすることもできます。
<defs>
の使用に注意してください。私はこれが外部SVGを持つことのいいところだと思います。すべてをきちんと整理しておくことができます。 (それがなければ、コンテンツは2回表示されます。)style.css
を取り除き、単にCSSをstyles-and-defsファイル内に配置しました。inline
要素であるためです。 。このギャップをなくすには、そのSVGにstyle="display: block;"
を設定するだけです。SVGは素晴らしいですが、サポートが少なすぎるように見えるかもしれませんが、いくつかの素晴らしいことは可能です。これが一部の人々の役に立てば幸いです。
OS X 10.12.6でテスト済みOK:
リンク先 であるSVG仕様の定義から:
CSS2セレクターは、その内容が正式なドキュメント構造の一部ではないため、(概念的に)複製されたDOMツリーに適用できません。
つまり、1.svgのセレクターは、複製されたDOMツリーには適用されません。
では、代わりに別の.svgからスタイルシートを単に参照しないのはなぜですか?これは、すべてのブラウザで、<use>
と<image>
の両方で機能するはずです。
もう1つのオプションは、メインのsvgドキュメント(1.svg)の<use>
要素にスタイルを設定することです。スタイルはそこから複製されたツリーにもカスケードされます。
このようにしてみてください:
広場:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
<rect x="558.5" y="570" width="5" height="5" id="rectangle" />
</svg>
これを使って:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="style.css" type="text/css"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
<use xlink:href="another.svg#rectangle" class="blue"/>
</svg>
<svg>
要素にはxlink:href
属性がありません。外部画像を含める必要がある場合は、<image>
要素を使用してください。