前言

上一个使用的主题Joe3自带优化嵌入的哔哩哔哩视频功能,于是为了适配我自己写了一个。

https://www.halo.run/store/apps/app-ZxiPb

代码

<script>
  class BilibiliEmbed extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
    }

    connectedCallback() {
      const bvid = this.getAttribute('bvid');
      if (bvid) {
        this.render(bvid);
      }
    }

    render(bvid) {
      const wrapper = document.createElement('div');
      wrapper.classList.add('bilibili-video-wrapper');

      const iframe = document.createElement('iframe');
      iframe.src = `https://player.bilibili.com/player.html?bvid=${bvid}`;
      iframe.frameborder = "0";
      iframe.allow = "autoplay; fullscreen; encrypted-media";
      iframe.allowfullscreen = true;

      wrapper.appendChild(iframe);

      const style = document.createElement('style');
      style.textContent = `
                    .bilibili-video-wrapper {
                        position: relative;
                        width: 100%;
                        height: 0;
                        padding-bottom: 56.25%;
                    }
                    .bilibili-video-wrapper iframe {
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                    }
                `;

      this.shadowRoot.append(style, wrapper);
    }
  }
customElements.define('bilibili-video', BilibiliEmbed);
</script>

使用

<bilibili-video bvid="BV18Z4y1V7ZJ"></bilibili-video>

预览

2025-01-27

更新

<script>
  /**
   * BilibiliEmbed 类用于在网页中嵌入Bilibili视频
   * 它通过创建一个自定义元素来实现视频的嵌入
   */
  class BilibiliEmbed extends HTMLElement {
    /**
     * 构造函数
     * 初始化影子DOM,用于封装组件的样式和结构
     */
    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
    }

    /**
     * 当元素被连接到DOM时调用
     * 负责根据元素的属性来渲染Bilibili视频
     */
    connectedCallback() {
      const bvid = this.getAttribute('bvid');
      const autoplay = this.getAttribute('autoplay') === 'true' ? '1' : '0';
      const muted = this.getAttribute('muted') === 'true' ? '1' : '0';

      if (bvid) {
        this.render(bvid, autoplay, muted);
      }
    }

    /**
     * 渲染视频
     * @param {string} bvid - 视频的Bilibili ID
     * @param {string} autoplay - 是否自动播放视频('1'为是,'0'为否)
     * @param {string} muted - 是否静音视频('1'为是,'0'为否)
     */
    render(bvid, autoplay, muted) {
      // 创建视频容器
      const wrapper = document.createElement('div');
      wrapper.classList.add('bilibili-video-wrapper');

      // 创建iframe嵌入视频
      const iframe = document.createElement('iframe');
      iframe.src = https://player.bilibili.com/player.html?bvid=${bvid}&autoplay=${autoplay}${muted === '1' ? '&muted=1' : ''};
      iframe.frameborder = "0";
      iframe.allow = "autoplay; fullscreen; encrypted-media";
      iframe.allowfullscreen = true;

      // 将iframe添加到容器中
      wrapper.appendChild(iframe);

      // 创建样式
      const style = document.createElement('style');
      style.textContent = 
        .bilibili-video-wrapper {
          position: relative;
          width: 100%;
          height: 0;
          padding-bottom: 56.25%; /* 保持16:9的宽高比 */
        }
        .bilibili-video-wrapper iframe {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
        }
      ;

      // 将样式和容器添加到DOM中
      this.shadowRoot.append(style, wrapper);
    }
  }

  // 定义自定义元素,使其可以在HTML中使用<bilibili-video>标签
  customElements.define('bilibili-video', BilibiliEmbed);
</script>

使用

不自动播放+不静音

什么选项都不带。

<bilibili-video bvid="BV18Z4y1V7ZJ"></bilibili-video>

不自动播放+静音

<bilibili-video bvid="BV18Z4y1V7ZJ" autoplay="false" muted="true"></bilibili-video>

自动播放+静音

<bilibili-video bvid="BV18Z4y1V7ZJ" autoplay="true" muted="true"></bilibili-video>

自动播放+不静音

由于浏览器策略,不一定生效。

<bilibili-video bvid="BV18Z4y1V7ZJ" autoplay="true" muted="false"></bilibili-video>

预览

不自动播放+不静音

不自动播放+静音

自动播放+静音

自动播放+不静音