elementFromPoint() という API があった
2018年の初記事です。今年も宜しくお願い致します。
さて、まだまだ DOM 操作には知らないことが沢山…。
document.elementFromPoint()
という API があった。ページ左上からの X・Y 座標値を与えると、その位置にある要素を取得できるというモノだ。
検証用のデモページを作った。
マウスカーソルを任意の要素に重ねると、その要素を取得して CSS セレクタ表現をポインタ付近に表示する。
作り方
予め CSS で html
要素と body
要素を画面いっぱいに広げておく。必須ではないが、コンテンツが少ないと body
要素の下の html
要素が見えてしまうので、body
要素を広げて置いておくと良いかと。
html,
body {
margin: 0;
padding: 0; /* 基本は margin だけで十分だけど */
width: 100%;
height: 100%;
}
サンプルページで作ったコードは以下のとおり。
document.addEventListener('DOMContentLoaded', (loadEvent) => {
// ポインタ要素を生成しておく
const pointer = document.createElement('div');
// position: fixed を使うと完全にフローして画面外にはみ出てもスクロールバーが表示されたりしなくなる
pointer.setAttribute('style', 'display: inline-block; position: fixed; top: -1000px; border: 1px solid #ccc; border-radius: 4px; padding: 10px; background: #fff; opacity: .7;');
// スクロールバーは html 要素が出すので body 要素配下にいるポインタ要素はスクロールバーの下に隠れる
document.body.appendChild(pointer);
// 直前にポイントした要素を控えておく
let previousElement;
// 引数の要素の CSS セレクタ表現を作る
const getQuerySelector = (elem) => {
const tagName = elem.tagName.toLowerCase();
let querySelector = tagName;
if(elem.id.trim()) {
querySelector += '#' + elem.id.trim();
}
if(elem.className.trim()) {
querySelector += '.' + Array.apply(null, elem.classList).join('.');
}
return querySelector;
};
// ポインタの位置にある要素を取得し CSS セレクタ表現を表示する
const getElementFromPoint = (event) => {
// ポインタの位置を設定する
pointer.style.top = (event.y + 10) + 'px';
pointer.style.left = (event.x + 5) + 'px';
// 指定の座標位置にある要素を取得する
const elementFromPoint = document.elementFromPoint(event.x, event.y);
// 要素がないか直前の要素と同じなら中止
if(!elementFromPoint || elementFromPoint === previousElement) {
return;
}
// 直前の要素として控えておく
previousElement = elementFromPoint;
// 当該要素の CSS セレクタ表現を作る
let parentElement = elementFromPoint;
let tagName = elementFromPoint.tagName.toLowerCase();
let querySelector = getQuerySelector(elementFromPoint);
// 親要素に遡って CSS セレクタ表現を作る
while(tagName !== 'html') {
parentElement = parentElement.parentElement;
tagName = parentElement.tagName.toLowerCase();
querySelector = getQuerySelector(parentElement) + ' > ' + querySelector;
}
// ポインタ要素に表示する
pointer.textContent = querySelector;
}
document.addEventListener('mousemove', getElementFromPoint); // マウス操作中
document.addEventListener('click' , getElementFromPoint); // マウスボタン押下時
});
マウスカーソルに追随するポインタとか、選択した要素の CSS セレクタ表現を作る関数とか、余計な処理が混じっているので、肝心の箇所だけ抜き出してみる。
// クリックした座標位置の要素を取得する
document.addEventListener('click', (event) => {
const clickedElement = document.elementFromPoint(event.x, event.y);
});
なんとコレだけ。
要素が絶対配置とかで重なっている時は、一番上に表示されている要素が取得できるようだ。
Dragula
というドラッグ処理を扱えるライブラリで見かけた。