getClientRects()とgetBoundingClientRect()の違いとその動作のまとめ
ワタシ、ニホンゴ ニガテ。ダカラ コレ ヨク イミ ワカラナイ。
Element.getClientRects() * 一行一行のボックス情報を取得する
Element.getBoundingClientRect * ボーダー辺で囲まれた領域のボックス情報を取得できる
getBoundingClientRect()はDrag&Dropを実装する際に使った事があったので、Rectが取得できるヤツだと認識してたけど、getClientRects()とか知らなかった。で、上記の説明を読んだのは良いんだけど、どう違うのかが理解できなかった。
なので、getClientRects()とgetBoundingClientRect()がどういうヤツなのかをメモを残しとく。なお、このメモはあくまでIE6での動作のまとめであって、Firefox3での動作なんて眼中にないのであしからず。
getBoundingClientRect()
ある要素のクライアント座標(画面スクロールに関わらず表示中の領域の左上が必ず(0, 0)になる)を取得する。ただし、左/上が2pxずれるバグ?あり。
動作例1
こんなHTML/スクリプトを用意。
<html> <head> <style type="text/css"> <!-- #hoge { width: 100px; height: 100px; background-color: red; position: absolute; left: 20px; top: 20px; } --> </style> <script type="text/javascript"> <!-- window.onload = function() { var elem = document.getElementById("hoge"); var rect = elem.getBoundingClientRect(); var buf = []; for(key in rect) { buf.push(key + " : " + rect[key]); } alert(buf.join("\n")); } --> </script> </head> <body> <div id="hoge"></div> </body> </html>
動かしてみる。
getBoundingClientRect_1 posted by (C)terurou
ちゃんと「2pxずれた」座標が取得できてますね!
動作例2
今度は画面をスクロールさせた状態で動かしてみる。
<html> <head> <style type="text/css"> <!-- #hoge { width: 100px; height: 100px; background-color: red; position: absolute; /* 座標を遥か彼方へ… */ left: 1000px; top: 1000px; } --> </style> <script type="text/javascript"> <!-- window.onload = function() { document.onclick = function() { var elem = document.getElementById("hoge"); var rect = elem.getBoundingClientRect(); var buf = []; for(key in rect) { buf.push(key + " : " + rect[key]); } alert(buf.join("\n")); } } --> </script> </head> <body> <div id="hoge"></div> </body> </html>
で、画面をスクロールさせた状態で実行。
getBoundingClientRect_2 posted by (C)terurou
ちゃんとクライアント座標が取得できた。この場合もしっかりと「2pxずれ」が発生しますです。
getClientRects()
上手に説明できる日本語力/文章力がないので図示しながら。
こんなHTMLがあるとする。
<html> <head> <style type="text/css"> <!-- #hoge { width: 200px; background-color: #FDD; position: absolute; left: 20px; top: 20px; } #hogehoge { border: 1px solid red; } --> </style> </head> <body> <div id="hoge"> <p id="hogehoge">前書いた萌ディタを再起動するだけのAutoHotkeyスクリプトがma.laさんにクリップされてた。まだ萌ディタ使ってるって事かなぁ。</p> </div> </body> </html>
このHTMLを画面表示するとこんな感じになる。
getClientRects_1 posted by (C)terurou
で、この画面の p#hogehoge に対してgetClientRects()してみる。
var elem = document.getElementById("hogehoge"); var rects = elem.getClientRects(); alert(rects.length); // 5 alert(rects[0].top); // 22 alert(rects[0].bottom); // 41 alert(rects[0].left); // 22 alert(rects[0].right); // 222 alert(rects[1].top); // 41 alert(rects[2].top); // 59 alert(rects[3].top); // 77 alert(rects[4].top); // 95
これじゃ判りづらいので、取得できた値を図示してみる。
getClientRects_2 posted by (C)terurou
なるほど、確かに「一行一行のボックス情報を取得する」ですねぇ…。特筆すべきところとしては、
- 1行目のheightにborder-top-widthが含まれる。
- 最終行のheightにborder-bottom-widthが含まれる。
- やっぱり2pxずれる。
- 取得できる座標はクライアント座標なので、スクロールさせた状態だと値が変わる。
getClientRects()の注意点
仕様なのかバグなのか判らんのですが、widthが指定されている要素に対してgetClientRects()すると、複数行のはずなのに1行として扱われてしまうっぽい。
<html> <head> <style type="text/css"> <!-- #hoge { width: 200px; background-color: #FDD; position: absolute; left: 20px; top: 20px; } --> </style> </head> <body> <div id="hoge">前書いた萌ディタを再起動するだけのAutoHotkeyスクリプトがma.laさんにクリップされてた。まだ萌ディタ使ってるって事かなぁ。</div> </body> </html>
var elem = document.getElementById("hoge"); var rects = elem.getClientRects(); alert(rects.length); // 1
予告
2pxずれるバグ?の原因/対処法についてはだいたい調査済みなので、今度書く予定。