纯JS中的跨源iframe中的视差效果?

时间:2018-05-30 11:26:02

标签: javascript html iframe parallax

所以我有一个包含iframe元素的文档。

我的文档和iframe有不同的来源。

我希望在文档中加载时,将此iframe内容看作是视差

例如,文档如下所示:

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>blah</p>
<p>blah</p>
<p>blah</p>
<p>blah</p>
<iframe src="parallax.html" width="200" height="200">
<p>blah</p>
<p>blah</p>
<p>blah</p>
</body>
</html>

parallax.html只包含适合窗口大小的图像。

我认为parallax.html应该有脚本来确定窗口相对于屏幕的位置并调整图像位置。我尝试了一些东西,例如:

  • 将滚动事件监听器添加到顶部窗口,但由于它们是跨域的,因此受限制
  • 获取document.body.scrollTop,但它始终返回0
  • 获取getBoundingClientRect()个参数,但top也返回0

这可能吗?我错过了什么吗?是的,我必须使用vanilla JS,没有jQuery或其他库。

1 个答案:

答案 0 :(得分:1)

正如您所注意到的,跨域限制使得这有点棘手。您的父框架将无法访问内部变量或在其子框架中设置侦听器,反之亦然。它可以访问的属性非常有限,可在此处查看:https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Cross-origin_script_API_access

此外,我相信iframe中的document.body.scrollTopgetBoundingClientRect()相对于框架本身,就像框架是迷你窗口一样。您可能无法在iframe中访问所需的信息,但应该能够从父框架中获取该信息。

使用postMessage

在跨源帧之间传递信息的传统方式是使用iframe.contentWindow.postmessage

在这种情况下,一个简单的实现是将您的滚动侦听器附加到父框架,该框架将消息发送到您的子框架。它看起来像这样:

父文档

var iframeElement = document.getElementById('my-parallax'); // give your iframe this id
window.addEventListener('scroll', () => {
  var rect = iframeElement.getBoundingClientRect();
  var dataToSend = {
    scrollY: window.scrollY,
    left: rect.left, right: rect.right,
    bottom: rect.bottom, top: rect.top
  };
  var targetOrigin = '*'; // can change this if you know it
  iframeElement.contentWindow.postMessage(dataToSend, targetOrigin);
});

然后在 parallax.html

window.addEventListener('message', function (e) {
  var data = e.data;
  if (e.source === window.parent) { // check if the sender was the parent
    // use data.scrollY, data.top... etc. here
  }
});

对这种方法的警告(以及一般的postMessage)是,不能保证iframe的UI将与父窗口同步更新。除非在任一帧上有大量计算,否则差异应该很小。据我所知,在使用跨域iframe时这是不可避免的。