Google 地图不会放弃按键以在阴影中输入 DOM
Google maps does not relinquish key presses to input in shadow DOM
对于复制代码的长度,我们深表歉意。问题是 google 映射 API 似乎不会将某些按键转发到阴影 DOM 中的元素。如果您加载以下代码(提供您自己的 API 键),使用箭头键平移地图,然后尝试在屏幕顶部输入内容,您会看到 'm'、'k',并且箭头键(至少)不会进入输入。奇怪的是,这些键的 keypress
和 keydown
事件会在输入时触发,但重要的是 input
不会。尽管地图不再具有焦点,但箭头键仍然能够平移地图。输入底部输入(在常规 DOM 中)按预期工作。
注意:
- 如果您不使用箭头键平移地图,输入将按预期工作。
- 如果您不将输入放在阴影中 DOM 它会按预期工作。
所以问题似乎是,一旦地图获得键盘焦点,它就拒绝放弃它。我尝试给 div 输入一个 tabindex
并 focus
ing 它。不解决问题。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0">
<meta charset="utf-8"/>
<style>
html, body {
font-family: sans-serif;
width: 100%;
height: 100%;
margin: 0;
}
#map-div {
width: 100%;
height: 100%;
}
#shadow {
position: fixed;
top: 50px;
left: 50px;
z-index: 1000;
}
#input {
position: fixed;
top: 100px;
left: 50px;
z-index: 1000;
}
</style>
</head>
<body>
<div id="shadow"></div>
<input id="input"></input>
<div id="map-div"></div>
<script>
document.querySelector('#shadow')
.attachShadow({mode:'open'})
.appendChild(document.createElement('input'));
window._mapsLoaded = () => {
let map = new google.maps.Map(document.querySelector('#map-div'), {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=$API_KEY&callback=_mapsLoaded"></script>
</body>
</html>
作为解决方法,您可以使用 window.location
方法转到 dom 文档中的输入位置。我已通过向 #shadow
输入添加 onfocus
事件来修改您的示例。
<script>
document.querySelector('#shadow')
.attachShadow({mode:'open'})
.appendChild(document.createElement('input'));
window._mapsLoaded = () => {
let map = new google.maps.Map(document.querySelector('#map-div'), {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
});
}
function focusOnShadow() {
window.location.hash = '#tries';
}
</script>
这是 jsfiddle 上的工作示例。
更新:我发现我只设法解决了 'm' 和 'k' 问题,但方向键行为仍然存在。
这是一个bug in the google maps API。我临时解决了它如下:
let mapDiv = document.querySelector('#map-div');
let map = new google.maps.Map(mapDiv, {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
keyboardShortcuts: false, // disables the API keyboard handlers
});
// The added cases on the arrows are to cope with Edge's
// non-standard key values
let keymap = key => {
switch (key) {
case 'ArrowUp':
case 'Up':
return 38;
case 'ArrowDown':
case 'Down':
return 40;
case 'ArrowLeft':
case 'Left':
return 37;
case 'ArrowRight':
case 'Right':
return 39;
case 'Add':
case 'Equal':
return 187;
case 'Minus':
case 'Subtract':
return 189;
default: return 0; // browsers give keyCode 0 for unknown
}
};
let keydownHandler = e => {
let value = e.keyCode || keymap(e.key);
switch (value) {
case 107: // numpad add
case 187: // equals/plus
map.setZoom(map.getZoom() + 1);
break;
case 109: // numpad subtract
case 189: // minus
map.setZoom(map.getZoom() - 1);
break;
case 37: // left
map.panBy(-50, 0);
break;
case 38: // up
map.panBy(0, 50);
break;
case 39: // right
map.panBy(50, 0);
break;
case 40: // down
map.panBy(0, -50);
break;
}
};
// Here we'll track keydowns only when the mouse is over
// the map container:
mapDiv.addEventListener('mouseenter', e => {
document.addEventListener('keydown', keydownHandler);
});
mapDiv.addEventListener('mouseleave', e => {
document.removeEventListener('keydown', keydownHandler);
});
基本上我禁用地图 API 键盘处理并替换我自己的。您可以调整箭头键上的平移值以使滚动更流畅,但我现在已经超时了。
对于复制代码的长度,我们深表歉意。问题是 google 映射 API 似乎不会将某些按键转发到阴影 DOM 中的元素。如果您加载以下代码(提供您自己的 API 键),使用箭头键平移地图,然后尝试在屏幕顶部输入内容,您会看到 'm'、'k',并且箭头键(至少)不会进入输入。奇怪的是,这些键的 keypress
和 keydown
事件会在输入时触发,但重要的是 input
不会。尽管地图不再具有焦点,但箭头键仍然能够平移地图。输入底部输入(在常规 DOM 中)按预期工作。
注意:
- 如果您不使用箭头键平移地图,输入将按预期工作。
- 如果您不将输入放在阴影中 DOM 它会按预期工作。
所以问题似乎是,一旦地图获得键盘焦点,它就拒绝放弃它。我尝试给 div 输入一个 tabindex
并 focus
ing 它。不解决问题。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0">
<meta charset="utf-8"/>
<style>
html, body {
font-family: sans-serif;
width: 100%;
height: 100%;
margin: 0;
}
#map-div {
width: 100%;
height: 100%;
}
#shadow {
position: fixed;
top: 50px;
left: 50px;
z-index: 1000;
}
#input {
position: fixed;
top: 100px;
left: 50px;
z-index: 1000;
}
</style>
</head>
<body>
<div id="shadow"></div>
<input id="input"></input>
<div id="map-div"></div>
<script>
document.querySelector('#shadow')
.attachShadow({mode:'open'})
.appendChild(document.createElement('input'));
window._mapsLoaded = () => {
let map = new google.maps.Map(document.querySelector('#map-div'), {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=$API_KEY&callback=_mapsLoaded"></script>
</body>
</html>
作为解决方法,您可以使用 window.location
方法转到 dom 文档中的输入位置。我已通过向 #shadow
输入添加 onfocus
事件来修改您的示例。
<script>
document.querySelector('#shadow')
.attachShadow({mode:'open'})
.appendChild(document.createElement('input'));
window._mapsLoaded = () => {
let map = new google.maps.Map(document.querySelector('#map-div'), {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
});
}
function focusOnShadow() {
window.location.hash = '#tries';
}
</script>
这是 jsfiddle 上的工作示例。
更新:我发现我只设法解决了 'm' 和 'k' 问题,但方向键行为仍然存在。
这是一个bug in the google maps API。我临时解决了它如下:
let mapDiv = document.querySelector('#map-div');
let map = new google.maps.Map(mapDiv, {
center: new google.maps.LatLng(39.75, -86.16),
zoom: 11,
keyboardShortcuts: false, // disables the API keyboard handlers
});
// The added cases on the arrows are to cope with Edge's
// non-standard key values
let keymap = key => {
switch (key) {
case 'ArrowUp':
case 'Up':
return 38;
case 'ArrowDown':
case 'Down':
return 40;
case 'ArrowLeft':
case 'Left':
return 37;
case 'ArrowRight':
case 'Right':
return 39;
case 'Add':
case 'Equal':
return 187;
case 'Minus':
case 'Subtract':
return 189;
default: return 0; // browsers give keyCode 0 for unknown
}
};
let keydownHandler = e => {
let value = e.keyCode || keymap(e.key);
switch (value) {
case 107: // numpad add
case 187: // equals/plus
map.setZoom(map.getZoom() + 1);
break;
case 109: // numpad subtract
case 189: // minus
map.setZoom(map.getZoom() - 1);
break;
case 37: // left
map.panBy(-50, 0);
break;
case 38: // up
map.panBy(0, 50);
break;
case 39: // right
map.panBy(50, 0);
break;
case 40: // down
map.panBy(0, -50);
break;
}
};
// Here we'll track keydowns only when the mouse is over
// the map container:
mapDiv.addEventListener('mouseenter', e => {
document.addEventListener('keydown', keydownHandler);
});
mapDiv.addEventListener('mouseleave', e => {
document.removeEventListener('keydown', keydownHandler);
});
基本上我禁用地图 API 键盘处理并替换我自己的。您可以调整箭头键上的平移值以使滚动更流畅,但我现在已经超时了。