如何正确调整Facebook Canvas app(iFrame)的大小?

时间:2011-01-14 21:02:30

标签: javascript canvas facebook browser-cache

我需要在更新页面内容后调整画布大小。我可以通过

明确地做到这一点
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());

如何让它发挥作用?

关于这个问题的更多评论:

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

    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
    4. 如何控制Facebook Canvas应用的大小?

10 个答案:

答案 0 :(得分:7)

不要为定时自动调整大小编写自己的函数。 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元素的问题。尝试使用事件订阅回调:

   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/

答案 1 :(得分:3)

我设法让.setSize()延迟执行(正如各种论坛所建议的那样):

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

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

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

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

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

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元素变得非常眨眼。

答案 2 :(得分:2)

我们的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

答案 3 :(得分:1)

我们遇到了FB.Canvas函数无法正常工作的问题,虽然所有内容都已正确初始化,因为他们在跨域JS设置中使用'IFRAME'代替iframe,因此没有XHTML兼容性

我们通过原型化我们自己的createElement函数并覆盖它们来解决这个问题。 在你加入Facebook all.js之后把它放好吧:

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

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

然后跟着它:

FB.Canvas.setAutoResize();

您不必使用10,只需要小于页面最小尺寸的内容。然后FB.Canvas.setAutoResize()应该继续并再次使其适当高度并继续更新。只有当内容再次缩小时,您需要再次呼叫FB.Canvas.setSize({ width: 760, height: 10 });的唯一时间。

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:0)

这对我有用:

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

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

答案 9 :(得分:0)

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

另外,我不建议使用body计算身高。

这对我有用:

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

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