Quill 编辑器自定义视频模块:将 iframe 替换为 video 标签

Quill 编辑器自定义视频模块:将 iframe 替换为 video 标签

前言

在使用 Quill 富文本编辑器时,默认的视频模块会使用 <iframe> 标签来嵌入视频。这种方式在某些场景下存在一些问题,特别是对于竖屏视频,iframe 可能无法正确显示视频的宽高比。本文将介绍如何自定义 Quill 的视频模块,将默认的 iframe 标签替换为 <video> 标签,从而更好地控制视频的显示效果。

问题背景

Quill 编辑器默认的视频模块存在以下问题:

  1. 竖屏视频显示问题:使用 iframe 嵌入视频时,竖屏视频可能无法正确显示宽高比
  2. 控制能力有限:iframe 标签对视频的控制能力较弱,无法直接使用 HTML5 的原生视频控制功能
  3. 样式定制困难:iframe 的样式定制相对复杂,不如 video 标签灵活

解决方案

通过创建自定义的 Video Blot(Quill 中的内容块类型),我们可以完全控制视频标签的渲染方式,使用原生的 <video> 标签替代默认的 <iframe> 标签。

实现步骤

步骤一:创建自定义视频模块

在 Vue 项目的 src/components/Editor 目录下创建 quill 文件夹,然后创建 video.js 文件:

javascript 复制代码
import Quill from "quill";

const BlockEmbed = Quill.import("blots/block/embed");

class Video extends BlockEmbed {
  static create(value) {
    let node = super.create();
    // 处理字符串 URL 或对象格式 {url: "..."}
    const url =
      typeof value === "string" ? value : value && value.url ? value.url : "";
    node.setAttribute("src", url);
    node.setAttribute("controls", "controls");
    node.setAttribute("width", "100%");
    node.setAttribute("style", "height: auto;");
    return node;
  }

  static value(node) {
    return {
      url: node.getAttribute("src"),
    };
  }
}

Video.blotName = "video";
Video.tagName = "video";

export default Video;

代码说明:

  • BlockEmbed:Quill 提供的块级嵌入基类,用于创建自定义的嵌入内容
  • create(value):创建视频节点的方法
    • 处理两种输入格式:字符串 URL 或对象格式 {url: "..."}
    • 设置视频属性:srccontrolswidth
    • height: auto 确保视频保持原始宽高比
  • value(node):从 DOM 节点提取视频 URL 的方法
  • blotName:Blot 的名称,必须与 Quill 的视频模块名称一致
  • tagName:使用的 HTML 标签名称,这里使用 video

步骤二:在编辑器组件中注册自定义模块

src/components/Editor/index.vue 文件中引入并注册自定义视频模块:

vue 复制代码
<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import Video from "./quill/video";

// 注册自定义视频模块
Quill.register(Video, true);

export default {
  name: "Editor",
  // ... 其他代码
};
</script>

关键点:

  • 必须在创建 Quill 实例之前注册自定义模块
  • Quill.register(Video, true) 中的第二个参数 true 表示如果已存在同名模块则强制覆盖

步骤三:确保工具栏包含视频按钮

在 Quill 的配置中,确保工具栏包含视频按钮:

javascript 复制代码
modules: {
  toolbar: [
    // ... 其他工具栏按钮
    ["link", "image", "video"]  // 链接、图片、视频
  ]
}

完整代码示例

video.js 完整代码

javascript 复制代码
import Quill from "quill";

const BlockEmbed = Quill.import("blots/block/embed");

class Video extends BlockEmbed {
  static create(value) {
    let node = super.create();
    // 处理字符串 URL 或对象格式 {url: "..."}
    const url =
      typeof value === "string" ? value : value && value.url ? value.url : "";
    node.setAttribute("src", url);
    node.setAttribute("controls", "controls");
    node.setAttribute("width", "100%");
    node.setAttribute("style", "height: auto;");
    return node;
  }

  static value(node) {
    return {
      url: node.getAttribute("src"),
    };
  }
}

Video.blotName = "video";
Video.tagName = "video";

export default Video;

Editor/index.vue 关键部分

vue 复制代码
<template>
  <div>
    <div class="editor" ref="editor" :style="styles"></div>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { getToken } from "@/utils/auth";
import Video from "./quill/video";

// 注册自定义视频模块
Quill.register(Video, true);

export default {
  name: "Editor",
  data() {
    return {
      Quill: null,
      options: {
        theme: "snow",
        modules: {
          toolbar: [
            ["bold", "italic", "underline", "strike"],
            ["blockquote", "code-block"],
            [{ list: "ordered" }, { list: "bullet" }],
            [{ indent: "-1" }, { indent: "+1" }],
            [{ size: ["small", false, "large", "huge"] }],
            [{ header: [1, 2, 3, 4, 5, 6, false] }],
            [{ color: [] }, { background: [] }],
            [{ align: [] }],
            ["clean"],
            ["link", "image", "video"]  // 包含视频按钮
          ],
        },
        placeholder: "请输入内容",
      },
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      const editor = this.$refs.editor;
      this.Quill = new Quill(editor, this.options);
    },
  },
};
</script>

效果对比

修改前(默认 iframe)

html 复制代码
<iframe src="video-url" frameborder="0" allowfullscreen="true"></iframe>

修改后(自定义 video)

html 复制代码
<video src="video-url" controls="controls" width="100%" style="height: auto;"></video>

优势

使用自定义 video 标签后,获得了以下优势:

  1. 更好的宽高比控制height: auto 确保视频保持原始宽高比,竖屏视频可以正确显示
  2. 原生视频控制 :使用 HTML5 原生的 controls 属性,提供更好的用户体验
  3. 样式定制灵活:可以直接通过 CSS 定制视频样式
  4. 性能优化:video 标签比 iframe 更轻量,性能更好

注意事项

  1. URL 格式处理:代码中已经处理了字符串和对象两种格式的 URL,确保兼容性
  2. 注册时机:必须在创建 Quill 实例之前注册自定义模块
  3. 浏览器兼容性:确保目标浏览器支持 HTML5 video 标签
  4. 视频格式:video 标签支持的视频格式取决于浏览器,建议使用 MP4、WebM 等通用格式

常见问题

Q: 为什么视频 URL 显示为 undefined?

A: 这是因为 Quill 传递的可能是字符串格式的 URL,而不是对象格式。代码中已经处理了这种情况:

javascript 复制代码
const url =
  typeof value === "string" ? value : value && value.url ? value.url : "";

Q: 如何自定义视频样式?

A: 可以在 CSS 中直接针对 video 标签添加样式:

css 复制代码
.editor video {
  max-width: 100%;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

Q: 如何添加更多视频属性?

A: 在 create 方法中可以添加更多属性,例如:

javascript 复制代码
node.setAttribute("preload", "metadata");
node.setAttribute("poster", "poster-image-url");
node.setAttribute("muted", "muted");

总结

通过自定义 Quill 的视频模块,我们成功地将默认的 iframe 标签替换为 video 标签,解决了竖屏视频显示问题,并获得了更好的控制能力和用户体验。这个方案简单易用,只需要创建自定义 Blot 并注册即可,无需修改 Quill 的核心代码。

参考资源

相关推荐
线束线缆组件品替网2 小时前
TE Linx RF 物联网射频模块的 RF 线缆连接设计思路
数码相机·物联网·测试工具·电脑·音视频·pcb工艺
EasyCVR2 小时前
视频融合平台EasyCVR赋能旅游景区构建全场景可视化监控新体系
音视频·旅游
EasyGBS3 小时前
EasyGBS扩展市场:视频监控系统的“应用商店”,拖入安装、即装即用!
音视频
八月的雨季 最後的冰吻3 小时前
FFmepg-- 38-ffplay源码-缓冲区 audio_buf调试
c++·ffmpeg·音视频
lxmyzzs3 小时前
【硬核部署】在 RK3588上部署毫秒级音频分类算法
人工智能·分类·音视频
LeeZhao@3 小时前
【狂飙全模态】灵曦星灿视频助手-影视级音画同步视频生成
人工智能·语言模型·音视频·agi
数智前线3 小时前
火山引擎智能3D视频启动商业化,计划落地直播应用
3d·音视频·火山引擎
杰克崔3 小时前
vscode的缓存文件夹及查看进程读写的文件
ide·vscode·编辑器
昨日之日200614 小时前
SCAIL - 自然流畅的AI角色动画生成软件 照片跳舞 虚拟偶像 WebUI+ComfyUI工作流 一键整合包下载
人工智能·音视频