【问题标题】:Auto resize iframe height when the height of the iframe contents change (same domain)当 iframe 内容的高度发生变化时自动调整 iframe 高度(同域)
【发布时间】:2012-12-16 06:50:52
【问题描述】:

我正在页面内加载 iframe,iframe 内容的长度会不时更改。我已经实施了以下解决方案。但是高度是固定的,因为只有在 iframe.onload 时才会调用 dyniframesize。

是否可以不时调整 iframe 的大小以改变 iframe 的高度?

<iframe src ="popup.html" frameborder="0" marginheight="0" marginwidth="0" frameborder="0" scrolling="auto" id="ifm" name="ifm" onload="javascript:dyniframesize('ifm');" width="100%"></iframe> 

function dyniframesize(down) { 
var pTar = null; 
if (document.getElementById){ 
pTar = document.getElementById(down); 
} 
else{ 
eval('pTar = ' + down + ';'); 
} 
if (pTar && !window.opera){ 
//begin resizing iframe 
pTar.style.display="block" 
if (pTar.contentDocument && pTar.contentDocument.body.offsetHeight){ 
//ns6 syntax 
pTar.height = pTar.contentDocument.body.offsetHeight +20; 
pTar.width = pTar.contentDocument.body.scrollWidth+20; 
} 
else if (pTar.Document && pTar.Document.body.scrollHeight){ 
//ie5+ syntax 
pTar.height = pTar.Document.body.scrollHeight; 
pTar.width = pTar.Document.body.scrollWidth; 
} 
} 
} 
</script> 

【问题讨论】:

    标签: javascript html css iframe


    【解决方案1】:

    据我所知,没有一种非常自然的方法可以做到这一点,但有一些选择。

    setInterval()

    您可以使用setInterval() 重复检查 iframe 的内容高度并在需要时进行调整。这很简单,但效率很低。

    事件监听器

    iframe 内容(以及高度)中的任何内容更改通常由某些事件触发。例如,即使您从 iframe 外部添加内容,“添加”也可能是由单击按钮触发的。这可能对您有用:Live demo here (click).

    var myIframe = document.getElementById('myIframe');
    
    window.addEventListener('click', resizeIframe);
    window.addEventListener('scroll', resizeIframe);
    window.addEventListener('resize', resizeIframe);
    
    myIframe.contentWindow.addEventListener('click', resizeIframe);
    
    function resizeIframe() {
      console.log('resize!');
    }
    

    变异观察者

    此解决方案适用于所有最新的浏览器 - http://caniuse.com/mutationobserver

    Live demo here (click).

    这真的很简单,应该可以捕捉到相关的变化。如果没有,您可以将其与上面的事件侦听器解决方案结合使用,以确保更新!

    var $myIframe = $('#myIframe');
    var myIframe = $myIframe[0];
    
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    
    myIframe.addEventListener('load', function() {
      setIframeHeight();
    
      var target = myIframe.contentDocument.body;
    
      var observer = new MutationObserver(function(mutations) {
        setIframeHeight();
      });
    
      var config = {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true
      };
      observer.observe(target, config);
    });
    
    myIframe.src = 'iframe.html';
    
    function setIframeHeight() {
      $myIframe.height('auto');
      var newHeight = $('html', myIframe.contentDocument).height();
      $myIframe.height(newHeight);
    }
    

    荣誉奖:上溢/下溢事件。

    Read about it here(有很多)。

    see my demo here(在 IE 11 中不起作用!)。

    这个很酷的解决方案,但它不再适用于 IE。可能可以对其进行调整,但我宁愿使用上述解决方案之一,即使对于旧版浏览器我不得不回退到 1 秒 setInterval,只是因为它比这个解决方案简单得多。

    【讨论】:

    • 使用 MutationObserver 时,在 webkit 中它会在图像加载完成之前触发,因此您必须检测添加/更改的 IMG 节点,然后将负载侦听器附加到它们。
    • @DavidBradshaw 最后一个选项似乎再次可行。
    【解决方案2】:

    实际上,您应该通过访问父窗口并更改 iframe 的高度从 iframe 执行此操作。

    因为 iframe 中的文档通常会更好地知道它的主体是否改变了它的大小(您实际上可以将它绑定到 body.onload 之类的东西,而不是使用间隔来检查 iframe 中是否发生了变化)。

    【讨论】:

    • 您能否详细说明一下身体如何“知道”它何时改变了它的大小?
    • 如果你的 iframe 能够动态改变它的高度(比如从 ajax 请求中插入一些数据),你总是可以“注入”像 window.parent.document.getElementById('myframe').style 这样的代码.height = window.document.body.offsetHeight (或类似的东西)在从 ajax 插入数据之后。否则,您将只需要在 iframe 中的 body.onload 中使用此代码。
    • 您的回答并不是建议“动态”调整大小。很明显,在进行 ajax 调用后必须手动调用更新函数。他希望它能够自我更新。
    • 好吧,(IMO)你的解决方案对我来说似乎有点“肮脏”,而且也很明显。我只是建议了“正确的做法”(如我所见)。
    • 我注意到第一个解决方案效率低下,为了完整性我将其包括在内。第二种解决方案干净简单。第三个很棒而且超级高效,但是很复杂。我一会儿再补充。我不会亲自对此投反对票,我只是指出您的答案与问题无关..我想您可能会很高兴知道这一点。
    【解决方案3】:

    您可以使用自定义事件在iframe 和父级之间发出信号。

    iframe

    if (window.parent !== window) {
      window.oldIframeHeight = 0;
      window.setInterval(function() {
          var currentHeight = document.body.offsetHeight;
          if (currentHeight !== window.oldIframeHeight) {
              window.parent.postMessage(currentHeight.toString(), "*");
              window.oldIframeHeight = currentHeight;
          }
      }, 100)
    }
    

    然后,在父级中:

    window.addEventListener("message", function (e) {
        var h = parseInt(e.data, 10);
        if (!isNaN(h)) {
            $('#iframe').height(h)
        }
    }, false);
    

    【讨论】:

      【解决方案4】:

      我编写了一个小型库,它使用了 mutationaObserver 和 eventListners,回退到 IE8-10 的 setInterval 并且适用于同域和跨域。它可以调整高度和宽度。

      http://davidjbradshaw.github.io/iframe-resizer/

      【讨论】:

      • 由于页面的复杂性,仅对我有用。感谢您与社区分享。很好的例子。 =) +1
      【解决方案5】:

      iFrame 视图

      <script type="text/javascript">
          var height = $("body").outerHeight();
          parent.SetIFrameHeight(height);
      </script>
      

      主视图

      <script type="text/javascript">
          SetIFrameHeight = function(height) {
              $("#iFrameWrapper").height(height);
          }
      </script>
      

      【讨论】:

        猜你喜欢
        • 2016-10-11
        • 2014-04-25
        • 2016-06-13
        • 2014-11-06
        • 2011-08-23
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        相关资源
        最近更新 更多