简体   繁体   English

window.matchMedia 在 iframe 中不起作用

[英]window.matchMedia not works in iframe

I'm detecting device orientation using window.matchMedia .我正在使用window.matchMedia检测设备方向。 The following code works as intended - every orientation change is logged to console with correct value:以下代码按预期工作 - 每个方向更改都以正确的值记录到控制台:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Test App</title>
  </head>
  <body>
    <script type="application/javascript">
        let isIframe= () => {
            try {
                return window.self !== window.top;
            } catch (e) {
                return true;
            }
        }    

         let onOrientationChange = () => {
            const isLandscape = window.matchMedia("(orientation: landscape)").matches;
            console.log("Event: " + (isIframe() ? "Iframe " : "") + "landscape:" + isLandscape);
        }

        let mediaQueryList = window.matchMedia("(orientation: landscape)");
        
        console.log("Onload: " + (isIframe() ? "Iframe " : "") + "landscape:" + mediaQueryList.matches);

        mediaQueryList.addListener(onOrientationChange);
    </script>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root">Hello World in Iframe</div>
  </body>
</html>

But when I run that page in iframe , callback registered using addListener is not fired.但是当我在iframe中运行该页面时,不会触发使用addListener注册的回调。 In iframe , I only get singular log line - Onload: Iframe landscape:true , regardless of the device orientation.iframe中,我只得到单数日志行 - Onload: Iframe landscape:true ,无论设备方向如何。

 <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root">Hello World</div>
    <iframe id="game" src="iframeContent.html" frameborder="0" style="width: 960px; height: 600px;"></iframe>
  </body>

I'm using addListener instead of addEventListener , because the second one function is not working on all Safari versions.我正在使用addListener而不是addEventListener ,因为第二个 function 不适用于所有 Safari 版本。

Tested on Safari 14 and on Dev Tools of Chrome and Firefox.在 Safari 14 以及 Chrome 和 Firefox 的开发工具上进行了测试。

My question is - why addListener callback is not invoked in iframe .我的问题是 - 为什么在iframe中没有调用addListener回调。

Thank you.谢谢你。

If the iframe does not get it's size to change because it has fixed width and height, thus resize related events cannot be triggered inside it includingMediaQueryList events regarding orientation .如果 iframe 没有改变它的大小,因为它具有固定的宽度和高度,因此无法在其中触发调整大小相关事件,包括有关orientationMediaQueryList事件。

You can do two things to get this working;你可以做两件事来让它工作; you can make your iFrame width and height to be 100% , or you can let the media query detection code inside the main window and pass the orientation state using postMessage when it triggers a change event.您可以使您的 iFrame 宽度和高度为100% ,或者您可以让主 window 内的媒体查询检测代码并传递方向postMessage当它触发 change 事件时。

1) Changing iFrame size to 100% so it resizes when landscape/portrait orientation event triggers 1) 将 iFrame 大小更改为100% ,以便在横向/纵向方向事件触发时调整大小

In the main page, make the body full height and the iframe full width/height (using CSS).在主页中,使主体全高和 iframe 全宽/高(使用 CSS)。

body {
  height: 100vh;
  margin: 0;
}

iframe {
  width: 100%;
  height: 100%;
}

Live example that you can test: https://zikro.gr/dbg/so/65704468/您可以测试的实时示例: https://zikro.gr/dbg/so/65704468/

2) Media query detection on the main page and use postMessage to send a message to iFrame when orientation event triggers 2) 主页媒体查询检测,并在orientation事件触发时使用postMessage向iFrame发送消息

index.html : index.html

<iframe src="iframe.html"></iframe>
<script>
  let iframe = document.querySelector('iframe');

  let onOrientationChange = () => {
    iframe.contentWindow.postMessage({
      isLandscape: window.matchMedia("(orientation: landscape)").matches
    }, '*');
  }

  iframe.addEventListener('load', onOrientationChange);

  const mediaQueryList = window.matchMedia("(orientation: landscape)");

  mediaQueryList.addListener(onOrientationChange);
</script>

iframe.html : iframe.html

<script>
  window.addEventListener("message", (event) => {
    if (event.data.isLandscape) {
      console.log('iFrame Landscape');
    } else {
      console.log('iFrame Portrait');
    }
  });
</script>

Live example that you can test: https://zikro.gr/dbg/so/65704468/pm/您可以测试的实时示例: https://zikro.gr/dbg/so/65704468/pm/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM