【问题标题】:window.matchMedia not works in iframewindow.matchMedia 在 iframe 中不起作用
【发布时间】:2021-01-13 14:59:57
【问题描述】:

我正在使用window.matchMedia 检测设备方向。以下代码按预期工作 - 每个方向更改都会以正确的值记录到控制台:

<!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>

但是当我在iframe 中运行该页面时,不会触发使用addListener 注册的回调。在 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>

我正在使用addListener 而不是addEventListener,因为第二个功能不适用于所有 Safari 版本。

在 Safari 14 以及 Chrome 和 Firefox 的开发工具上测试。

我的问题是 - 为什么在 iframe 中没有调用 addListener 回调。

谢谢。

【问题讨论】:

    标签: javascript html matchmedia


    【解决方案1】:

    如果 iframe 没有改变它的大小,因为它具有固定的宽度和高度,因此无法在其中触发调整大小相关的事件,包括与 orientation 相关的 MediaQueryList 事件。

    你可以做两件事来让它工作;您可以将 iFrame 的宽度和高度设置为100%,或者您可以让媒体查询检测代码在主窗口内,并在触发更改事件时使用postMessage 传递方向状态。

    1) 将 iFrame 大小更改为 100%,以便在触发横向/纵向事件时调整大小

    在主页中,使正文全高和 iframe 全宽/高(使用 CSS)。

    body {
      height: 100vh;
      margin: 0;
    }
    
    iframe {
      width: 100%;
      height: 100%;
    }
    

    您可以测试的实时示例:https://zikro.gr/dbg/so/65704468/

    2) 主页上的媒体查询检测,并在orientation事件触发时使用postMessage向iFrame发送消息

    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:

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

    您可以测试的实时示例:https://zikro.gr/dbg/so/65704468/pm/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-27
      • 2021-03-05
      • 2012-12-15
      • 2012-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      相关资源
      最近更新 更多