Ckeditor编辑器集成Kityformula公式库

498 阅读1分钟

先看结果:

image.png 会弹出

image.png

会以base64图片形式插入ckeditor编辑器 image.png

1.先把Kityformula库解压放到public文件夹下

image.png

2.写一个CKeditor的插件,逻辑就是在编辑器的toolbar里加一个按钮,点击后弹一个弹窗,然后将公式编辑器Kityformula用iframe的形式嵌入这个弹窗里

iframe的代码:

<script setup lang="ts">
const props = defineProps(["latex"]);
const param = props.latex?.split(",,zyx,,")[0];
const data = encodeURIComponent(param);
const url = props.latex ? `/kityFormula.html?c=${data}` : "/kityFormula.html";
</script>

<template>
  <div>
    <iframe
      id="editor5-iframe"
      :src="url"
      frameborder="0"
      width="800px"
      height="390px"
    />
  </div>
</template>
<style scoped></style>

下面写Ckeditor插件 image.png KityformulaPlugin.js如下:

import ButtonView from "@ckeditor/ckeditor5-ui/src/button/buttonview";
import ContextualBalloon from "@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon";
import { addDialog } from "@/components/ReDialog";
import EditorDialog from "@/components/EditorDialog/index.vue";

export default class CustomDialogPlugin extends Plugin {
  static get requires() {
    return [ContextualBalloon];
  }

  static get pluginName() {
    return "CustomDialogPlugin";
  }

  init() {
    const editor = this.editor;

    // 监听双击事件
    // 这里其实是回显的逻辑,当公式已经被插入Ckeditor之后,双击,应该再次弹出公式编辑器,然后把公式放到公式编辑器里.下面的target.alt其实就是最下面---1处的latex
    editor.ui.on("update", () => {
      const editableElement = editor.ui.view.editable.element;

      if (editableElement && !this._dblClickHandler) {
        // 定义双击事件处理函数
        this._dblClickHandler = event => {
          const target = event.target;
          const dataPath = target.alt;
          if (dataPath && dataPath.split(",,zyx,,")[1]) {
            this.openDialog(editor, dataPath);
          }
        };

        // 添加双击事件监听器
        editableElement.addEventListener("dblclick", this._dblClickHandler);
      }
    });

    // 注册工具栏按钮
    editor.ui.componentFactory.add("kityformulaDialog", locale => {
      const view = new ButtonView(locale);

      view.set({
        label: "公式",
        tooltip: true,
        withText: true // 自定义图标
      });

      view.on("execute", () => {
        this.openDialog(editor);
      });

      return view;
    });
  }

  /**
   * 打开自定义弹窗
   * @param {ButtonView} buttonView - 触发弹窗的按钮视图
   */
  openDialog(editor, latex) {
    addDialog({ // 这是自己封装的弹窗组件,你也可以用template内的弹窗组件,这里其实只是要在点击弹窗确认按钮后,获取公式编辑器里的内容,写入Ckeditor内部
      title: "数学公式(请在英文输入法下输入)",
      fullscreenIcon: true,
      closeOnClickModal: false,
      width: "840px",
      height: "400px",
      props: {
        open: open,
        latex: latex
      },
      contentRenderer: () => EditorDialog,
      beforeSure: done => {
        const node = document.getElementById("editor5-iframe");
        const kfe = node.contentWindow.kfe;
        kfe.execCommand("get.image.data", function (data) {
          const latex = kfe.execCommand("get.source");
          // kityFormula为空,不执行插入
          if (latex === "\\placeholder ") {
            done();
            return;
          }
          //1处-------------这里想给img添加其他属性,好传latex,但是都会被ckeditor强制删除,有没有人能提供添加属性的方式.这里加不了其他属性,所以就直接加在了alt上.
          const formulaImgHtml = `
            <img
              src="${data.img}"
              alt="${latex + ",,zyx,,kityFormula"}" 
              class="kityformula-style-css"
            />
          `;
          editor.model.change(() => {
            const viewFragment = editor.data.processor.toView(formulaImgHtml);
            const modelFragment = editor.data.toModel(viewFragment);
            editor.model.insertContent(modelFragment);
          });
          done();
        });
      }
    });
  }
}

3.在CKeditor编辑器组件里添加这个插件就行了

image.png

4.总结(只要理解下面的原理,上面都不看,都能自己摸索出来) 原理就是给ckeditor(或者你的编辑器)添加一个按钮,点击能弹出弹窗,在弹窗里嵌入iframe,src的值就是public里面的那个formula.html,这样就能将公式编辑器显示在弹窗里. 然后,可以在公式编辑器里输入公式,然后在点击弹窗的确认按钮的时候,将公式编辑器里的latex格式的公式,转换成base64的图片(同时把latex保存在img的alt上).插入到你的编辑器里(我这是ckeditor).然后,双击ckeditor内你写好的公式,应该再弹出公式编辑器,然后拿到img的alt,其实就是latex,给公式编辑器,让公式编辑器展示,以供修改. 核心代码就是

kfe.execCommand("get.image.data", function (data) {
          const latex = kfe.execCommand("get.source");
          // kityFormula为空,不执行插入
          if (latex === "\\placeholder ") {
            done();
            return;
          }
          const formulaImgHtml = `
            <img
              src="${data.img}"
              alt="${latex + ",,zyx,,kityFormula"}"
              class="kityformula-style-css"
            />
          `;
          editor.model.change(() => {
            const viewFragment = editor.data.processor.toView(formulaImgHtml);
            const modelFragment = editor.data.toModel(viewFragment);
            editor.model.insertContent(modelFragment);
          });
          done();
        });

11