SVGの重なり順序をJavaScriptで制御する「svg-z-order」
JavaScriptからSVG要素の重なり順(Z-Order)を操作するモジュールのご紹介。
SVG要素には、HTMLに使えるz-index
スタイルが効きません。
なので、重なり順を変更するには、単純に要素を並べ替える必要があります。
コードからDOM要素を並べ替えるにはNodeクラスのinsertBefore
メソッドが使えます。
Node
クラスはSVG要素SVGElement
の基本クラスですから、SVG要素でも使えます。
SVG関連最新記事:
takamints.hatenablog.jp
takamints.hatenablog.jp
ところで、SVG要素にはz-index
が効かないことを「SVGの致命的な欠陥」と言ってる人がいますが、さすがにそれは言い過ぎですよ。SVGは単体で存在できる画像ファイルであってHTMLとの直接的なつながりはありません。単体のSVGファイル中で図形の重なり順序をz-index
で定義されていると、画像としてどのように表示されるか理解しにくいはずです。要素の順序で重なり順序が決定される方が、SVG的に「よりシンプル」なんですね。
さらに「HTMLのDIVにSVGを入れてz-index
で…」などというヤヤコシイ方法が検索で出てくるのですが、これは既にSVGではなくなっていますから、一般的な解決法とはいえないように思います。全体のスケールを変えるとかViewportを移動したいとかいったシーンで困りそう。
というか、DOM要素の並べ替え自体は前述のようにinsertBeforeで簡単なんです。 DOMのベタな扱いに慣れていないと難しそうに思うのかもしれないですね。
ただし、ベタにやると「どれの前に持ってくる?」といったコードが煩雑になるのは確かです。 てことで怒りに任せて(?)npmを書きなぐりました。以降、このモジュールのサンプルとかAPIを説明します。
とりあえずは動くサンプル
以下は、このモジュールを使ったサンプルです。コードは下の方に掲載してます。 3つの円をクリックすると、その要素にドロップダウンで選ばれているメソッドを適用します。
使い方
このモジュールを使って、特定要素を最前面へ持ってくるコードを少し冗長に書いてみました。
//モジュール取得 var svgz = require("svg-z-order");// (1) //SVG要素 g#foo を最前面へ表示 var g = svg.getElementById("foo"); var svgzG = svgz.element(g); //(2) svgzG.toTop(); //(3) // D3.jsで使う(4) var d3 = require("d3"); var d3g = d3.select("#foo"); svgz.element(d3g.node()).toTop();
- モジュールをインポートして、
element
メソッドで、DOM要素を参照するインスタンスを作り- 最前面へ表示します。
- D3.jsを使っていますが、例として書いているだけで、依存関係はありません。
上の例では、Browserifyを使って、
var svgz = require("svg-z-orger");
でモジュールを取り込んでいますが、
HTMLで<script src="svg-z-order.js"/>
としている場合は、
(2)の行の svgz.element(g)
を、 svgz_element(g)
に変更して下さい。
require
できない環境ではグローバルスコープに定義します。
API
element(e:Element)
SVG要素を参照する SVGZElement クラスのインスタンスを返します。 Z-Orderを操作するAPIは SVGZElementクラスのメソッドです。
パラメータ
- e:Element - 参照するDOM要素を指定します。
SVGZElementクラス
SVGZElement.toTop()
参照している要素を最前面に移動。
SVGZElement.toBottom()
参照している要素を最背面に移動。
SVGZElement.moveUp(e:Element / n:number)
参照している要素を上(前面)へ移動。
パラメータ
- e:Element - この要素よりも上になるように移動します。
- n:number - 要素の並びの中でこの回数分だけ上へ移動します。
要素を指定したときはその要素よりも上へ。数値指定した場合は、その回数だけ上へ移動。
SVGZElement.moveDown(e:Element / n:number)
参照している要素を下(背面)へ移動。
パラメータ
- e:Element - この要素よりも下になるように移動します。
- n:number - 要素の並びの中でこの回数分だけ下へ移動します。
要素を指定したときはその要素よりも下へ。数値指定の場合は、その回数だけ下へ移動。
サンプルコード
一番上にあるサンプルのコードです。
/sample/web/index.js
リポジトリ
いくつになってもお勉強
JavaScriptのプログラムからSVG要素を最前面へもってくる方法を検索したら、結構微妙な情報が出てきたので少しインターネッツに失望しました。
曰く、
こういう情報を見て、当初「エラいヤヤコシイな」と思いましたが、どうにも納得がいかなくて、いろいろやってみているとDOMの標準機能で可能だと判明。
当初「複製作って、追加して、元のを消す」という処理手順をイメージしていましたが、移動できますね。
Node.appendChild
やNode.insertBefore
は、既にDOMツリーにある要素は移動するのですが、メソッド名を見る限りではそう思えないところが落とし穴かも。
いくつになってもお勉強です。
Node.js / npm 関連記事
takamints.hatenablog.jp takamints.hatenablog.jp takamints.hatenablog.jp takamints.hatenablog.jp takamints.hatenablog.jp