【问题标题】:How to resize Facebook Canvas app (iFrame) correctly?如何正确调整 Facebook Canvas 应用程序 (iFrame) 的大小?
【发布时间】:2011-01-14 21:02:30
【问题描述】:

我需要在更新页面内容后调整画布大小。我可以明确地做到这一点

FB.Canvas.setSize({ width: 760, height: 1480 });

但是,如果没有参数,它就不起作用,即.setSize()

另外,我可以调整高度

FB.Canvas.setAutoResize(true);

但只会增加 - 减少内容时不会减少高度。

以下行不起作用:

FB.Arbiter.inform("setSize", FB.Canvas._computeContentSize());
FB.Canvas.setSize(FB.Canvas._computeContentSize());

如何让它发挥作用?

关于这个主题的更多 cmets:

  1. http://developers.facebook.com/blog/post/93
  2. http://developers.facebook.com/docs/reference/javascript/fb.canvas.setautoresize

相关:

  1. facebook-api: what's Facebook Connect cross-domain receiver URL?
  2. facebook-app: how can i change the height of a resizeable iframe application?
  3. Document height grows on resize when setting canvas dimensions dynamically

您如何控制 Facebook Canvas 应用程序的大小?

【问题讨论】:

    标签: javascript canvas facebook browser-cache


    【解决方案1】:

    不要为定时自动调整大小编写自己的函数。 Fb 有一个:

    FB.Canvas.setAutoResize();
    

    如果您知道何时需要调整它的大小,请使用

    FB.Canvas.setSize()
    

    因此,如果您想在单击链接时变小,请将其粘贴在一个函数中,然后稍后调用该函数,例如:

    function sizeChangeCallback() {
        FB.Canvas.setSize();
      }
    
    //start some function or on click event - here i used jquery
    $("#something").click(function() {
      sizeChangeCallback()
    });
    

    您不需要设置明确的高度,但有时您可能会遇到动态 xfbml 元素(如 cmets 插件)的问题。尝试使用事件订阅回调:

       FB.Event.subscribe('xfbml.render', function(response) {
        FB.Canvas.setAutoResize();
      });
    

    http://developers.facebook.com/docs/reference/javascript/FB.Canvas.setSize/

    http://developers.facebook.com/docs/reference/javascript/FB.Canvas.setAutoResize/

    http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/

    【讨论】:

    • 重复相同的信息对这里的任何人都没有好处,不是吗?感谢FB.Event.subscribe('xfbml.render',...。最后的链接也值得一提,以防有人在没有阅读参考的情况下使用函数......
    • 重复什么信息?设置超时功能是一种hack,它没有考虑页面渲染时间,而setAutoResize已经是一个超时功能。
    • 另外值得注意的是,您不需要为 setSize(); 设置明确的高度或宽度;去工作。您只需要先使用正确的应用程序 ID 初始化应用程序。正如上面@Andrei 建议的那样,我倾向于在我的内容块之后包含两者。
    【解决方案2】:

    我已设法通过延迟其执行使.setSize() 正常工作(如各个论坛上所建议的那样):

    window.setTimeout(function() {
      FB.Canvas.setSize();
    }, 250);
    

    如果你有XFBLM元素,尤其是fb:comments,那么你需要在设置页面大小之前解析页面

    window.setTimeout(function() {
      FB.XFBML.parse();
      FB.Canvas.setSize();
    }, 250);
    

    请注意,您需要在内容块之后运行此脚本,否则请增加允许网络服务器和客户端浏览器在调整画布大小之前构建内容的时间间隔(以毫秒为单位)。

    这种方法只会增加页面的高度,不会降低它。您可以通过在上面的代码之前触发以下行来手动减少

    FB.Canvas.setSize({height: 480}); // min height - .setSize() won't reduce it
    

    但是,有一个缺点 - 由于双重调整大小,页面会闪烁。

    另外,有人建议在几个时间间隔内运行 .setSize 以解决延迟内容:

    FB.Array.forEach([300, 600, 1000, 2000], function(delay) {
      setTimeout(function() {
        FB.XFBML.parse();
        FB.Canvas.setSize();
      }, delay)
    });
    

    在这种情况下,页面和 XFBML 元素变得非常闪烁。

    【讨论】:

      【解决方案3】:

      我们的 iframe 中有页面,这些页面将内容附加到页面,然后允许用户在适当的位置刷新页面内的内容。在这些情况下,我们看到了同样的情况,内容不会在适当的时候缩小。

      FB.Canvas.setSize()调用_computeContentSize,如下图:

      _computeContentSize: function() {
        var body = document.body,
            docElement = document.documentElement,
            right = 0,
            bottom = Math.max(
              Math.max(body.offsetHeight, body.scrollHeight) +
                body.offsetTop,
              Math.max(docElement.offsetHeight, docElement.scrollHeight) +
                docElement.offsetTop);
      
        if (body.offsetWidth < body.scrollWidth) {
          right = body.scrollWidth + body.offsetLeft;
        } else {
          FB.Array.forEach(body.childNodes, function(child) {
            var childRight = child.offsetWidth + child.offsetLeft;
            if (childRight > right) {
              right = childRight;
            }
          });
        }
        if (docElement.clientLeft > 0) {
          right += (docElement.clientLeft * 2);
        }
        if (docElement.clientTop > 0) {
          bottom += (docElement.clientTop * 2);
        }
      
        return {height: bottom, width: right};
      },
      

      有问题的行在这里:

      bottom = Math.max(
            Math.max(body.offsetHeight, body.scrollHeight) +
              body.offsetTop,
            Math.max(docElement.offsetHeight, docElement.scrollHeight) +
              docElement.offsetTop);
      

      即使你的 iframe 内的内容缩小了,body.offsetHeight 的值也不会缩小。

      为了解决这个问题,我们制作了一个自定义版本的 computeContentSize 函数,它只咨询 docElement 的高度,如下所示:

      function rfComputeContentSize() {
        var body = document.body,
            docElement = document.documentElement,
            right = 0,
            bottom = Math.max(docElement.offsetHeight, docElement.scrollHeight) + docElement.offsetTop;
      
        if (body.offsetWidth < body.scrollWidth) {
          right = body.scrollWidth + body.offsetLeft;
        } else {
          FB.Array.forEach(body.childNodes, function(child) {
            var childRight = child.offsetWidth + child.offsetLeft;
            if (childRight > right) {
              right = childRight;
            }
          });
        }
        if (docElement.clientLeft > 0) {
          right += (docElement.clientLeft * 2);
        }
        if (docElement.clientTop > 0) {
          bottom += (docElement.clientTop * 2);
        }
      
        return {height: bottom, width: right};
      }
      

      任何时候我们想要调整大小并且知道内容可能会缩小,我们将使用自定义函数将内容传递给 setSize(例如 FB.Canvas.setSize(rfComputeContentSize())),并且任何时候我们知道内容只会成长,我们将使用标准的 FB.Canvas.setSize() 函数。

      请注意,我们使用的是 setAutoGrow() 并且我没有检查,但我假设它使用相同的函数来确定大小。我们禁用了对 setAutoGrow() 的调用,并且必须警惕在适当的时间调用 setSize()。

      在 Facebook 上记录了这个错误:https://developers.facebook.com/bugs/228704057203827

      【讨论】:

        【解决方案4】:

        我们遇到了一个问题,即他们的 FB.Canvas 函数不起作用,尽管一切都已正确初始化,因为他们在跨域 JS 设置中使用“IFRAME”而不是 iframe,因此不兼容 XHTML。

        我们通过原型化我们自己的 createElement 函数并覆盖他们的函数来解决这个问题。 在你包含 Facebooks all.js 之后把它放在右边:

        document.__createElement = document.createElement;
        document.createElement = function(tagName) {
                    return document.__createElement(tagName.toLowerCase());
        }
        

        【讨论】:

          【解决方案5】:

          有点多余的功能,但这篇文章解释了为什么你不能动态地做到这一点,并提供了最简单的解决方案...... http://www.twistermc.com/36764/shrink-facebook-tabs/ 答案很简单: 将其缩小到非常小,然后在暂停后使用 AutoGrow 将其调整为正确的大小......爱丽丝梦游仙境风格。

          • 我说最简单,因为从开发人员和用户的角度来看,这会减慢大约 1/4 秒的速度,并且用户会看到滚动条的微小闪光...

          【讨论】:

            【解决方案6】:

            鲍比的回答很好。我唯一要补充的是,有些人通过执行以下操作成功地缩小了页面:

            FB.Canvas.setSize({ width: 760, height: 10 });

            然后跟着它:

            FB.Canvas.setAutoResize();

            您不必使用 10,只要小于页面的最小尺寸即可。然后FB.Canvas.setAutoResize() 应该继续并再次使其正确高度并继续更新。唯一需要再次调用FB.Canvas.setSize({ width: 760, height: 10 }); 的情况是内容再次缩小。

            这样做的危险在于,如果 FB.Canvas.setAutoResize(); 不起作用,您的内容可能会被截断。

            【讨论】:

            • 感谢您的贡献,但是,您在重复我的回答(除了最后一句,确实值得一提)。
            【解决方案7】:

            这些都不适合我。确保在结束标记之前键入。

            <div id="fb-root"></div>
            <script type="text/javascript"> 
             window.fbAsyncInit = function() {
            
             //Der folgende Code ändert die Grösse des iFrames alle 100ms 
            FB.Canvas.setAutoResize(100);
            
            };
            (function() {
            var e = document.createElement('script');
            e.async = true;
            e.src = document.location.protocol +
             '//connect.facebook.net/en_US/all.js';
             document.getElementById('fb-root').appendChild(e);  
             }());
            
            </script>    
            

            【讨论】:

              【解决方案8】:

              我尝试使用FB.Canvas.setSize(e); 调整我的应用程序大小,但它根本没有调整大小。

              我查看了 Facebook Javascript,发现 FB.Canvas.setSize 调用了 FB.Arbiter.inform('setSize',e) 函数。

              如果我直接从我的代码中调用 FB.Arbiter.inform('setSize',{ width: 760, height: 1480 }) 函数,画布会正确调整大小。

              【讨论】:

                【解决方案9】:

                这对我有用:

                <script type='text/javascript'>
                window.onload=function() {
                  FB.Canvas.setSize({width:760,height:document.body.offsetHeight});
                }
                </script>
                

                请注意,您不需要 FB.init,除非您出于其他原因使用它。

                【讨论】:

                  【解决方案10】:

                  当调整到最小高度时,不要忘记让它比原来大一点,以考虑水平滚动条和一些浏览器添加的一些额外像素,否则你最终会得到垂直滚动。

                  另外我不建议使用body 来计算高度。

                  这对我有用:

                  window.fbAsyncInit = function() 
                  {FB.Canvas.setSize({height:document.getElementById('m_table').offsetHeight+40});}
                  

                  其中 m_table 是包含我所有内容的表 ID(您可以改用 div)。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多