在阴影 DOM 元素上触发事件,该元素被光照 DOM 中的元素覆盖(不是父元素)
Trigger an event on a shadow DOM element that is overlaid by an element in the light DOM (not a parent)
我正在尝试获取阴影 DOM table 单元格的坐标,该单元格可能(或可能不)在其前面显示叠加元素。可点击的覆盖元素可能跨越多个单元格,因此它们不一定是我需要坐标的单元格的子元素。
我无法让事件像我预期的那样通过 table 冒泡。我相信阴影的事件重新定位 DOM 可以防止事件在光 DOM 中产生时击中细胞( 我有点认为这是错误的方法无论如何,因为覆盖元素不是单元格的子元素,所以我希望坐标从 )
开始
"pointer-events: none;"属性 几乎可以满足我的要求,但是,我需要事件也能在灯光 DOM 覆盖元素上触发,所以我不知道是否是一个选项。
我认为避免将监听器附加到每个单元格以解决性能问题是个好主意(在最终应用程序中会有数百个单元格)
我正在使用原版 JavaScript
在提供的示例中,是否可以在单击上方 div 灰色时获取下方 table 单元格的正确坐标?
class Custom_Grid extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
});
this.shadowRoot.innerHTML = `
<style>
td {
height:50px; width:50px; border: 1px solid grey;
}
</style>
<table>
<tr>
<td id='x0y0'><slot name='x0y0'></slot></td>
<td id='x0y1'><slot name='x0y1'></slot></td>
<td id='x0y2'><slot name='x0y2'></slot></td>
</tr>
<tr>
<td id='x1y0'><slot name='x1y0'></slot></td>
<td id='x1y1'><slot name='x1y1'></slot></td>
<td id='x1y2'><slot name='x1y2'></slot></td>
</tr>
<tr>
<td id='x2y0'><slot name='x2y0'></slot></td>
<td id='x2y1'><slot name='x2y1'></slot></td>
<td id='x2y2'><slot name='x2y2'></slot></td>
</tr>
`;
}
connectedCallback() {
this.shadowRoot.addEventListener("click", (e) => {
if (e.target.matches('td'))
console.log(`Grid Cell: ${e.target.id}`)
});
}
}
window.customElements.define('custom-grid', Custom_Grid);
document.getElementById('grid_overlay').addEventListener("click", (e) => {
console.log("#overGrid Click")
});
#grid_overlay {
width: 100px;
height: 100px;
background-color: grey;
position: absolute;
/*pointer-events: none; <-- not an option?*/
}
<custom-grid>
<div slot='x1y0' id='grid_overlay'></div>
</custom-grid>
一种解决方案是暂时隐藏覆盖元素,以便通过 elementFromPoint()
方法获得被覆盖的元素。
if ( e.target.id === 'grid_overlay' ) {
console.log( 'overlay click' )
e.target.hidden = true
var el = this.shadowRoot.elementFromPoint( e.x, e.y )
if (el.id)
console.log( 'under: ', el.id )
e.target.hidden = false
}
class Custom_Grid extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
td {
height:50px; width:50px; border: 1px solid grey;
}
</style>
<table>
<tr>
<td id='x0y0'><slot name='x0y0'></slot></td>
<td id='x0y1'><slot name='x0y1'></slot></td>
<td id='x0y2'><slot name='x0y2'></slot></td>
</tr>
<tr>
<td id='x1y0'><slot name='x1y0'></slot></td>
<td id='x1y1'><slot name='x1y1'></slot></td>
<td id='x1y2'><slot name='x1y2'></slot></td>
</tr>
<tr>
<td id='x2y0'><slot name='x2y0'></slot></td>
<td id='x2y1'><slot name='x2y1'></slot></td>
<td id='x2y2'><slot name='x2y2'></slot></td>
</tr>
`;
}
connectedCallback() {
this.shadowRoot.addEventListener("click", (e) => {
if (e.target.matches('td'))
console.log(`Grid Cell: ${e.target.id}`)
else if (e.target.id === 'grid_overlay' ) {
console.log( 'overlay click ' )
e.target.hidden = true
var el = this.shadowRoot.elementFromPoint( e.x, e.y )
if (el.id)
console.log( 'under: ', el.id )
e.target.hidden = false
}
});
}
}
window.customElements.define('custom-grid', Custom_Grid);
#grid_overlay {
width: 100px;
height: 100px;
background-color: grey;
position: absolute;
}
<custom-grid>
<div slot='x1y0' id='grid_overlay'></div>
</custom-grid>
我正在尝试获取阴影 DOM table 单元格的坐标,该单元格可能(或可能不)在其前面显示叠加元素。可点击的覆盖元素可能跨越多个单元格,因此它们不一定是我需要坐标的单元格的子元素。
我无法让事件像我预期的那样通过 table 冒泡。我相信阴影的事件重新定位 DOM 可以防止事件在光 DOM 中产生时击中细胞( 我有点认为这是错误的方法无论如何,因为覆盖元素不是单元格的子元素,所以我希望坐标从 )
开始"pointer-events: none;"属性 几乎可以满足我的要求,但是,我需要事件也能在灯光 DOM 覆盖元素上触发,所以我不知道是否是一个选项。
我认为避免将监听器附加到每个单元格以解决性能问题是个好主意(在最终应用程序中会有数百个单元格)
我正在使用原版 JavaScript
在提供的示例中,是否可以在单击上方 div 灰色时获取下方 table 单元格的正确坐标?
class Custom_Grid extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
});
this.shadowRoot.innerHTML = `
<style>
td {
height:50px; width:50px; border: 1px solid grey;
}
</style>
<table>
<tr>
<td id='x0y0'><slot name='x0y0'></slot></td>
<td id='x0y1'><slot name='x0y1'></slot></td>
<td id='x0y2'><slot name='x0y2'></slot></td>
</tr>
<tr>
<td id='x1y0'><slot name='x1y0'></slot></td>
<td id='x1y1'><slot name='x1y1'></slot></td>
<td id='x1y2'><slot name='x1y2'></slot></td>
</tr>
<tr>
<td id='x2y0'><slot name='x2y0'></slot></td>
<td id='x2y1'><slot name='x2y1'></slot></td>
<td id='x2y2'><slot name='x2y2'></slot></td>
</tr>
`;
}
connectedCallback() {
this.shadowRoot.addEventListener("click", (e) => {
if (e.target.matches('td'))
console.log(`Grid Cell: ${e.target.id}`)
});
}
}
window.customElements.define('custom-grid', Custom_Grid);
document.getElementById('grid_overlay').addEventListener("click", (e) => {
console.log("#overGrid Click")
});
#grid_overlay {
width: 100px;
height: 100px;
background-color: grey;
position: absolute;
/*pointer-events: none; <-- not an option?*/
}
<custom-grid>
<div slot='x1y0' id='grid_overlay'></div>
</custom-grid>
一种解决方案是暂时隐藏覆盖元素,以便通过 elementFromPoint()
方法获得被覆盖的元素。
if ( e.target.id === 'grid_overlay' ) {
console.log( 'overlay click' )
e.target.hidden = true
var el = this.shadowRoot.elementFromPoint( e.x, e.y )
if (el.id)
console.log( 'under: ', el.id )
e.target.hidden = false
}
class Custom_Grid extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
td {
height:50px; width:50px; border: 1px solid grey;
}
</style>
<table>
<tr>
<td id='x0y0'><slot name='x0y0'></slot></td>
<td id='x0y1'><slot name='x0y1'></slot></td>
<td id='x0y2'><slot name='x0y2'></slot></td>
</tr>
<tr>
<td id='x1y0'><slot name='x1y0'></slot></td>
<td id='x1y1'><slot name='x1y1'></slot></td>
<td id='x1y2'><slot name='x1y2'></slot></td>
</tr>
<tr>
<td id='x2y0'><slot name='x2y0'></slot></td>
<td id='x2y1'><slot name='x2y1'></slot></td>
<td id='x2y2'><slot name='x2y2'></slot></td>
</tr>
`;
}
connectedCallback() {
this.shadowRoot.addEventListener("click", (e) => {
if (e.target.matches('td'))
console.log(`Grid Cell: ${e.target.id}`)
else if (e.target.id === 'grid_overlay' ) {
console.log( 'overlay click ' )
e.target.hidden = true
var el = this.shadowRoot.elementFromPoint( e.x, e.y )
if (el.id)
console.log( 'under: ', el.id )
e.target.hidden = false
}
});
}
}
window.customElements.define('custom-grid', Custom_Grid);
#grid_overlay {
width: 100px;
height: 100px;
background-color: grey;
position: absolute;
}
<custom-grid>
<div slot='x1y0' id='grid_overlay'></div>
</custom-grid>