Google 地图不会放弃按键以在阴影中输入 DOM

Google maps does not relinquish key presses to input in shadow DOM

对于复制代码的长度,我们深表歉意。问题是 google 映射 API 似乎不会将某些按键转发到阴影 DOM 中的元素。如果您加载以下代码(提供您自己的 API 键),使用箭头键平移地图,然后尝试在屏幕顶部输入内容,您会看到 'm'、'k',并且箭头键(至少)不会进入输入。奇怪的是,这些键的 keypresskeydown 事件会在输入时触发,但重要的是 input 不会。尽管地图不再具有焦点,但箭头键仍然能够平移地图。输入底部输入(在常规 DOM 中)按预期工作。

注意:

  1. 如果您不使用箭头键平移地图,输入将按预期工作。
  2. 如果您不将输入放在阴影中 DOM 它会按预期工作。

所以问题似乎是,一旦地图获得键盘焦点,它就拒绝放弃它。我尝试给 div 输入一个 tabindexfocusing 它。不解决问题。

<!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 键盘处理并替换我自己的。您可以调整箭头键上的平移值以使滚动更流畅,但我现在已经超时了。