将iframe传递到SPA中的其他组件(类似于Youtube)

时间:2019-06-20 20:16:53

标签: javascript html css vue.js

因此,由于一段时间以来,Youtube具有在浏览页面时最小化Youtube Player的功能,因此LolEsports.com在Twitch和Embeded Youtube Player中具有类似的功能。

基本上,我想为页面提供类似的功能:

  • 前端的提示
  • 在子网址上嵌入了YouTube播放器
  • 当我离开子网址时,我希望YouTube播放器移动到当前状态的角落,并且仍然存在

我想听听一些有关如何实现此目标的灵感,因为当我尝试状态重置时,将状态传递到其他组件时,并且播放停止了。

很想听听想法

2 个答案:

答案 0 :(得分:1)

简单的答案是:如in this answer所述,您不能移动iframe DOM节点而不会丢失其状态。

长答案是:您有其他选择。我认为您最好的选择是直接在“转角播放器”中播放视频,然后将其重新设置为页面的正确位置。为此,您需要自己与DOM进行一些交互,您可以通过在要显示视频的容器上设置ref来轻松实现。

最后,您将得到如下结果:

在App.vue中,您具有标准的router-view以及一些将包含实际视频的元素。

<template>
  <div id="app">
    <router-view/>
    <corner-player/>
  </div>
</template>

您将开始播放视频的页面将包含一些占位符元素,这些元素将用作放置视频的指导点:

<div class="player-container" ref="player"></div>

然后,我们使用生命周期挂钩获取正确的URL和样式,以发送给播放器。我使用一条简单的总线来更轻松地在应用程序周围传递事件,因为否则通常很难将数据传递到播放器组件。我们使用已安装的挂钩来设置视频,因为那是在第一个渲染周期发生时。 beforeDestroy生命周期使我们能够发送某种事件,将视频置于死角。

export default {
  name: "child1",

  mounted() {
    const container = this.$refs.player;
    const boundingBox = container.getBoundingClientRect();

    this.$bus.$emit("play-video", {
      url: "https://www.youtube.com/embed/dW4HCi1zZh8",
      styling: {
        position: "absolute",
        top: `${boundingBox.top}px`,
        left: `${boundingBox.left}px`,
        width: `${boundingBox.width}px`,
        height: `${boundingBox.height}px`,
        border: "3px dotted red"
      }
    });
  },

  beforeDestroy() {
    this.$bus.$emit("move-to-corner-player");
  }
};

然后,播放器组件将使用这两个事件,并确保应用了正确的样式。我不建议像在这里一样应用原始的CSS,但这是概念的证明。

<template>
  <div class="corner-player" :style="styling" v-if="url">
    <iframe
      width="1280"
      height="540"
      :src="url"
      frameborder="0"
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      allowfullscreen
    ></iframe>
  </div>
</template>

<script>
export default {
  name: "CornerPlayer",

  data() {
    return {
      styling: {},
      url: "",

      defaultStyling: {
        border: "3px solid blue",
        position: "fixed",
        bottom: 0,
        right: 0,
        height: "150px",
        width: "220px"
      }
    };
  },

  created() {
    this.$bus.$on("play-video", this.playVideo);
    this.$bus.$on("move-to-corner-player", this.moveToCornerPlayer);
  },

  beforeDestroy() {
    // Prevent memory leaks
    this.$bus.$off("play-video", this.playVideo);
    this.$bus.$off("move-to-corner-player", this.moveToCornerPlayer);
  },

  methods: {
    playVideo({ url, styling }) {
      this.url = url;
      this.styling = styling;
    },

    moveToCornerPlayer() {
      this.styling = {
        ...this.defaultStyling
      };
    }
  }
};
</script>

<style scoped>
iframe {
  width: 100%;
  height: 100%;
}
</style>

您可以在Codesandbox上玩这个游戏

Edit Pass an Iframe to different Components in an SPA (similar to Youtube)

答案 1 :(得分:0)

感谢Sumurai8!为了使 iframe 容器更具响应性,我对您的 CodeSandbox 进行了一些编辑:https://codesandbox.io/s/pass-an-iframe-to-different-components-forked-jeipq?file=/src/components/Child1.vue

所以现在容器将在滚动和刷新时缩放并保持在同一位置。