Experiencia en el uso del editor de texto enriquecido tinymce

Este artículo se divide en las siguientes funciones:

  1. Algunas configuraciones para la inicialización de tinymce
  2. Inserte títulos y resúmenes específicos entre las barras de herramientas y el texto
  3. Personalice los botones de la barra de herramientas para lograr funciones específicas
  4. Eliminar la función de carga de red al cargar imágenes
  5. Las imágenes pegadas se cargan por defecto
  6. Agregar función de marca de agua a las imágenes
  7. Realice la composición tipográfica con un solo clic

    1. Algunas configuraciones de inicialización de tinymce

          1. Primero, debe introducir los siguientes dos complementos

        cnpm install @tinymce/tinymce-vue --save Versión: 2.0.0

        cnpm install tinymce --save Versión: 5.0.3
        Nota: Cuando lo usé antes, descubrí que algunos complementos integrados no existían en las versiones tinymce 6 y superiores, lo que provocó que algunas funciones no estuvieran disponibles, así que marqué la versión aquí

        2. Después de descargar el complemento, debe encontrar la carpeta tinymce en node_modules, copiar la carpeta de máscaras dentro y colocarla en la carpeta pública del proyecto vue

   

        3. También necesita descargar un paquete de idioma para traducir el complemento al chino. La dirección de descarga es la siguiente

   Dirección del sitio web oficial: https://www.tiny.cloud/get-tiny/language-packages/     

    Encuentre zh-ch para descargar, de la siguiente manera:

        Después de eso, coloque el paquete de idioma descargado en la carpeta pública de vue y luego introdúzcalo en el código.El nombre del paquete de idioma que descargué es zh-Hans, que puede ser diferente de los demás, pero el efecto final es el mismo. Lo mismo, solo importe directamente de acuerdo con el nombre del archivo

        El siguiente es el código, algunos complementos y algunas configuraciones básicas introducidas

<template>
  <div class="editor_wraper">
    <editor :init="tinymceInit" v-model="content"> </editor>
  </div>
</template>

<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
  toolbar,
  fontsizeFormats,
  fontFormats,
  lineheightFormats,
} from "@/utils/tinymceConfig";
export default {
  data() {
    return {
      content: "",
      tinymceInit: {
        language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
        language: "zh-Hans", //语言类型
        skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
        quickbars_image_toolbar: "", // 选中媒体文件时的弹框
        // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
        toolbar: toolbar, //工具栏配置,设为false则隐藏
        menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
        height: 500, // 富文本高度
        model: 'dom', // 是否可拉伸富文本框
        fontsize_formats: fontsizeFormats, //字体大小
        font_formats: fontFormats, //字体样式
        lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
        placeholder: "在这里输入文字",
        branding: false, //tiny技术支持信息是否显示
        resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
        statusbar: false,  //最下方的元素路径和字数统计那一栏是否显示
        paste_data_images: true, //图片是否可粘贴
        elementpath: false, //元素路径是否显示
      },
    };
  },
  components: { Editor },
};
</script>

        Aquí hay algunas configuraciones en el archivo tinymceConfig presentado anteriormente

/**
 * @description: 工具栏配置
 * @return {*}
 */
export const toolbar = `
  undo redo restoredraft |
  removeformat|
  formatselect |
  subscript superscript |
  bold italic underline strikethrough link anchor |
  numlist bullist blockquote |
  alignleft aligncenter alignright alignjustify|
  quicklink searchreplace image|
  forecolor backcolor |
  fontselect fontsizeselect|
  outdent indent lineheight|`

/**
 * @description: 字体大小设置
 * @return {*}
 */
export const fontsizeFormats = `12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px`
/**
 * @description: 字体设置
 * @return {*}
 */
export const fontFormats = `微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;`
/**
 * @description: 行高设置
 * @return {*}
 */
export const lineheightFormats = "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5"

Después de configurar el contenido anterior, la página puede mostrar el siguiente efecto

2. Inserte un título específico y un resumen entre la barra de herramientas y el texto

        La forma de insertar el título y el resumen es usar el modo en línea para lograrlo, de la siguiente manera lo modifiqué según el código anterior

       Nota: si configura toolbar_persist en verdadero después de habilitar el modo en línea, aún debe hacer clic en su tinymce para mostrar la barra de herramientas en lugar de una pantalla fija, es probable que no eliminó el paquete de tinymce cuando lo eliminó a través de la desinstalación de npm antes Hay muchos paquetes de tinymce en node_modules. En este momento, debe eliminar todos sus node_modules y luego instalarlos nuevamente. El hoyo de la prueba personal

<template>
  <div class="editor_wraper">
    <div id="mytoolbar"></div>
    <el-input
      class="titleStyle"
      v-model="defaultTitle"
      type="textarea"
      resize="none"
      :autosize="{ minRows: 1, maxRows: 3 }"
      placeholder="请在这里输入标题"
    ></el-input>
    <el-input
      class="abstractStyle"
      v-model="defaultAbstract"
      type="textarea"
      resize="none"
      :autosize="{ minRows: 1 }"
      placeholder="摘要(可选)"
    ></el-input>
    <editor :init="tinymceInit" v-model="content"> </editor>
  </div>
</template>

<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
  toolbar,
  fontsizeFormats,
  fontFormats,
  lineheightFormats,
} from "@/utils/tinymceConfig";
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
  data() {
    return {
      defaultTitle: "",
      defaultAbstract: "",
      content: "",
      tinymceInit: {
        language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
        language: "zh-Hans", //语言类型
        skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
        quickbars_image_toolbar: "", // 选中媒体文件时的弹框
        // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
        toolbar: toolbar, //工具栏配置,设为false则隐藏
        menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
        height: 500, // 富文本高度
        model: 'dom', // 是否可拉伸富文本框
        fontsize_formats: fontsizeFormats, //字体大小
        font_formats: fontFormats, //字体样式
        lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
        placeholder: "在这里输入文字",
        branding: false, //tiny技术支持信息是否显示
        resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
        statusbar: false,  //最下方的元素路径和字数统计那一栏是否显示
        paste_data_images: true, //图片是否可粘贴
        elementpath: false, //元素路径是否显示

        inline: true, //使用内联模式
        toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
        fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
      },
    };
  },
  components: { Editor },
};
</script>

<style lang="scss">
.editor_wraper {
  width: 60%;
  height: 80vh;
  margin: 0 auto;
}
.mce-content-body{
  height: 100%;
  outline: none;
}
.titleStyle .el-textarea__inner {
  width: 100%;
  height: 56px;
  font-size: 24px;
  font-weight: 500;
  margin-top: 10px;
  padding-left: 0;
  border: none;
}
.abstractStyle .el-textarea__inner {
  font-size: 22px;
  font-weight: 500;
  color: #bbb;
  margin-top: 5px;
  padding-left: 0;
  border: none;
}
</style>

 Después de emparejar, se pueden mostrar los siguientes efectos

 

3. Personalice los botones de la barra de herramientas para lograr funciones específicas

        Hay tres pasos para crear un botón personalizado:

        1. Crear un método en mi archivo tinymceConfig

/**
 * @description: 自定义按钮
 * @param {*} editor
 * @return {*}
 */
export const customBtn = (editor) => {
  // 参数一:自定义名称,需要放置在工具栏中
  editor.ui.registry.addButton("customBtn", {
    icon: "brightness", // 显示的图标
    tooltip: '自定义按钮', // 提示文字
    onAction: function () {
      console.log("点击了自定义按钮")
    }
  })
}

        2. Referenciarlo en la configuración de tinymce

        3. Coloque el nombre personalizado que declaró en addButton en la barra de herramientas

      

        Finalmente, se mostrará el botón creado.


        Nota: si desea modificar el ícono, puede consultar algunas direcciones de íconos         proporcionadas en el sitio web oficial : https://www.tiny.cloud/docs/tinymce/6/editor-icon-identifiers/         

 4. Elimine la función de carga de red al cargar imágenes

        La llamada eliminación significa que volví a personalizar una imagen cargada por mí mismo. No utilicé la carga de imágenes en tinymce. El botón personalizado se puede crear de acuerdo con el método anterior. Aquí solo escribo cómo cargar imágenes.

/**
 * @description: 自定义图片上传
 * @param {*} editor
 * @return {*}
 */
export const imageUpload = (editor) => {
  editor.ui.registry.addButton("imageUpload", {
    icon: "image",
    tooltip: '上传图片',
    onAction: function () {
      var input = document.createElement("input");
      input.setAttribute("type", "file");
      input.setAttribute("accept", "image/*");
      input.onchange = function () {
        var file = this.files[0];
        if (file.size / 1024 / 1024 > 20) {
          failure("上传失败,图片大小请控制在 20M 以内");
        } else {
          let formData = new FormData();
          formData.append("picture", file);
          formData.append("action", "add");
          // 上传后的逻辑
          uploadImage({ formData }).then((res) => {
            var reader = new FileReader();
            reader.onload = function () {
              var id = "blobid" + new Date().getTime();
              var blobCache = tinymce.activeEditor.editorUpload.blobCache;
              var base64 = reader.result.split(",")[1];
              var blobInfo = blobCache.create(id, file, base64);
              blobCache.add(blobInfo);
              // 将图片插入到文本中
              editor.insertContent(`<img src="${blobInfo.blobUri()}"/>`);
            };
            reader.readAsDataURL(file);
          }).catch(() => {
            failure("上传出错,服务器开小差了");
          });
        }
      };
      // 触发上传
      input.click();
    },
  });
}

5. Las imágenes pegadas se pueden cargar de forma predeterminada

        Para usar la función de pegar y copiar, debe introducir el complemento de pegar directamente en la página

         importar "tinymce/plugins/paste"; solo impórtelo y luego agregue complementos en la configuración para la configuración

 Luego monitoree el contenido copiado a través de paste_postprocess en la configuración y escriba la lógica pegada en paste_postprocess

<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
  toolbar,
  fontsizeFormats,
  fontFormats,
  lineheightFormats,
  customBtn,
  imageUpload,
} from "@/utils/tinymceConfig";
import "tinymce/plugins/paste"; // 复制粘贴的插件
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
  data() {
    return {
      defaultTitle: "",
      defaultAbstract: "",
      content: "",
      tinymceInit: {
        language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
        language: "zh-Hans", //语言类型
        skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
        quickbars_image_toolbar: "", // 选中媒体文件时的弹框
        plugins: "paste", //插件配置
        // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
        toolbar: toolbar, //工具栏配置,设为false则隐藏
        menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
        height: 500, // 富文本高度
        model: "dom", // 是否可拉伸富文本框
        fontsize_formats: fontsizeFormats, //字体大小
        font_formats: fontFormats, //字体样式
        lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
        placeholder: "在这里输入文字",
        branding: false, //tiny技术支持信息是否显示
        resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
        statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
        paste_data_images: true, //图片是否可粘贴
        elementpath: false, //元素路径是否显示

        inline: true, // 使用内联模式
        toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
        fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
        // 粘贴内容时的回调
        paste_postprocess: (plugin, args) => {
          this.$nextTick(() => {
            // 获取当前编辑器标签
            const doc = tinymce.activeEditor.getBody();
            // 循序所有标签
            doc.childNodes.forEach(async (item) => {
              const tag = item.firstChild; // 获取当前标签下的第一个标签
              // 判断当前标签或当前标签下面的第一个标签是否是一个img
              if (item.localName === "img" || tag.localName === "img") {
                const src =
                  item.localName === "img"
                    ? item.getAttribute("src")
                    : tag.getAttribute("src");
                // 如果是则拿到当前标签的图片地址,传递给后端,进行保存
                const { data } = await uploadImgByUrl({ url: src });
                // 拼接后端保存后的图片地址
                const url = process.env.VUE_APP_BASE_API + data;
                // 然后将新地址重新赋值给img标签
                item.localName === "img"
                  ? item.setAttribute("src", url)
                  : tag.setAttribute("src", url);
              }
            });
          });
        },
        // 自定义工具栏配置
        setup: function (editor) {
          // 自定义图片上传功能
          customBtn(editor);
          // 图片上传
          imageUpload(editor);
        },
      },
    };
  },
  components: { Editor },
};
</script>

6. Agregue la función de marca de agua a las imágenes

        También creé un botón personalizado para realizar la función de agregar una marca de agua. Agregar una marca de agua aquí es agregar una marca de agua a todas las imágenes del artículo. Si tiene necesidades individuales, puede modificarlo usted mismo. Cree un botón personalizado para ver lo anterior forma

        Si hay demasiadas imágenes, puede tomar un poco más de tiempo agregar la marca de agua. Se recomienda agregar un estado de carga

/**
 * @description: 添加图片水印
 * @param {*} editor
 * @return {*}
 */
export const imageWatermark = (editor) => {
  editor.ui.registry.addButton("imageWatermark", {
    icon: "edit-image",
    tooltip: '添加图片水印',
    onAction: function () {
      const doc = tinymce.activeEditor.getBody()
      doc.childNodes.forEach(item => {
        const tag = item.firstChild
        // 单独修改img标签
        if (item.localName === "img" || tag.localName === "img") {
          editImages(tag)
        }
      })
    }
  })
}

/**
 * @description: 给图片添加水印
 * @param {*} child
 * @return {*}
 */
const editImages = (child) => {
  const src = child.getAttribute("src")
  var image = new Image();
  image.crossOrigin = 'anonymous';
  image.src = src;
  image.onload = async () => {
    // 创建canvas,并将创建的img绘制成canvas
    const canvas = document.createElement('canvas')
    canvas.width = child.width
    canvas.height = child.height
    const ctx = canvas.getContext('2d')
    ctx.drawImage(image, 0, 0)
    ctx.textAlign = "left"
    ctx.textBaseline = "top"
    ctx.font = "18px Microsoft Yahei"
    ctx.fillStyle = "rgba(255, 255, 255, 0.5)"
    ctx.rotate((Math.PI / 180) * 15)
    for (let i = 0; i < child.height / 120; i++) {
      for (let j = 0; j < child.width / 50; j++) {
        ctx.fillText("这是水印", i * 200, j * 100, child.width)
      }
    }
    const base64Url = canvas.toDataURL()
    setTimeout(() => {
      // 将添加好水印的图片重新插入到富文本中
      child.setAttribute("src", base64Url)
    }, 5000)
  }
}

7. Realice la composición tipográfica de una sola tecla

El método de composición tipográfica de un clic también crea un botón personalizado. El método de implementación es básicamente el mismo, es decir, después de obtener el nodo dom, se juzga la etiqueta del nodo correspondiente y luego se agregan diferentes estilos a la etiqueta correspondiente.

/**
 * @description: 一键排版
 * @param {*} editor
 * @return {*}
 */
const objLabel = {
  "h1": "title",
  "h2": "title",
  "h3": "title",
  "p": "paragraph"
}
const objStyle = {
  title: {
    "font-family": "微软雅黑",
    "font-size": "22px"
  },
  paragraph: {
    "font-size": "16px",
    "color": "red"
  }
}
export const oneClickLayout = (editor) => {
  // 参数一:自定义名称,需要放置在工具栏中
  editor.ui.registry.addButton("oneClickLayout", {
    icon: "orientation", // 显示的图标
    tooltip: '一键布局', // 提示文字
    onAction: function () {
      const doc = tinymce.activeEditor.getBody()
      doc.childNodes.forEach(item => {
        // 获取需要修改的标签
        const text = objLabel[item.localName]
        if (text) {
          // 找到对应样式循环进行配置
          for (let v in objStyle[text]) {
            item.style[v] = objStyle[text][v]
          }
        }
      })
    }
  })
}

En este punto, todas las funciones se han completado y el código de la función completa se adjunta a continuación.

<template>
  <div class="editor_wraper">
    <div id="mytoolbar"></div>
    <el-input
      class="titleStyle"
      v-model="defaultTitle"
      type="textarea"
      resize="none"
      :autosize="{ minRows: 1, maxRows: 3 }"
      placeholder="请在这里输入标题"
    ></el-input>
    <el-input
      class="abstractStyle"
      v-model="defaultAbstract"
      type="textarea"
      resize="none"
      :autosize="{ minRows: 1 }"
      placeholder="摘要(可选)"
    ></el-input>
    <editor :init="tinymceInit" v-model="content"> </editor>
  </div>
</template>

<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
  toolbar,
  fontsizeFormats,
  fontFormats,
  lineheightFormats,
  customBtn,
  imageUpload,
  oneClickLayout
} from "@/utils/tinymceConfig";
import "tinymce/plugins/paste";
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
  data() {
    return {
      defaultTitle: "",
      defaultAbstract: "",
      content: "",
      tinymceInit: {
        language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
        language: "zh-Hans", //语言类型
        skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
        quickbars_image_toolbar: "", // 选中媒体文件时的弹框
        plugins: "paste", //插件配置
        // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
        toolbar: toolbar, //工具栏配置,设为false则隐藏
        menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
        height: 500, // 富文本高度
        model: "dom", // 是否可拉伸富文本框
        fontsize_formats: fontsizeFormats, //字体大小
        font_formats: fontFormats, //字体样式
        lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
        placeholder: "在这里输入文字",
        branding: false, //tiny技术支持信息是否显示
        resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
        statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
        paste_data_images: true, //图片是否可粘贴
        elementpath: false, //元素路径是否显示

        inline: true, // 使用内联模式
        toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
        fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
        // 粘贴内容时的回调
        paste_postprocess: (plugin, args) => {
          this.$nextTick(() => {
            // 获取当前编辑器标签
            const doc = tinymce.activeEditor.getBody();
            // 循序所有标签
            doc.childNodes.forEach(async (item) => {
              const tag = item.firstChild; // 获取当前标签下的第一个标签
              // 判断当前标签或当前标签下面的第一个标签是否是一个img
              if (item.localName === "img" || tag.localName === "img") {
                const src =
                  item.localName === "img"
                    ? item.getAttribute("src")
                    : tag.getAttribute("src");
                // 如果是则拿到当前标签的图片地址,传递给后端,进行保存
                const { data } = await uploadImgByUrl({ url: src });
                // 拼接后端保存后的图片地址
                const url = process.env.VUE_APP_BASE_API + data;
                // 然后将新地址重新赋值给img标签
                item.localName === "img"
                  ? item.setAttribute("src", url)
                  : tag.setAttribute("src", url);
              }
            });
          });
        },
        // 自定义工具栏配置
        setup: function (editor) {
          // 自定义图片上传功能
          customBtn(editor);
          // 图片上传
          imageUpload(editor);
          // 一键布局
          oneClickLayout(editor)
        },
      },
    };
  },
  components: { Editor },
};
</script>

<style lang="scss">
.editor_wraper {
  width: 60%;
  height: 80vh;
  margin: 0 auto;
}
.mce-content-body {
  height: 100%;
  outline: none;
}
.titleStyle .el-textarea__inner {
  width: 100%;
  height: 56px;
  font-size: 24px;
  font-weight: 500;
  margin-top: 10px;
  padding-left: 0;
  border: none;
}
.abstractStyle .el-textarea__inner {
  font-size: 22px;
  font-weight: 500;
  color: #bbb;
  margin-top: 5px;
  padding-left: 0;
  border: none;
}
</style>

Aquí está el código del archivo tinymceConfig


/**
 * @description: 工具栏配置
 * @return {*}
 */
export const toolbar = `
  customBtn imageUpload oneClickLayout|
  undo redo restoredraft |
  removeformat|
  formatselect |
  subscript superscript |
  bold italic underline strikethrough link anchor |
  numlist bullist blockquote |
  alignleft aligncenter alignright alignjustify|
  quicklink searchreplace image|
  forecolor backcolor |
  fontselect fontsizeselect|
  outdent indent lineheight|`

/**
 * @description: 字体大小设置
 * @return {*}
 */
export const fontsizeFormats = `12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px`
/**
 * @description: 字体设置
 * @return {*}
 */
export const fontFormats = `微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;`
/**
 * @description: 行高设置
 * @return {*}
 */
export const lineheightFormats = "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5"

/**
 * @description: 自定义按钮
 * @param {*} editor
 * @return {*}
 */
export const customBtn = (editor) => {
  // 参数一:自定义名称,需要放置在工具栏中
  editor.ui.registry.addButton("customBtn", {
    icon: "brightness", // 显示的图标
    tooltip: '自定义按钮', // 提示文字
    onAction: function () {
      console.log("点击了自定义按钮")
    }
  })
}

/**
 * @description: 自定义图片上传
 * @param {*} editor
 * @return {*}
 */
export const imageUpload = (editor) => {
  editor.ui.registry.addButton("imageUpload", {
    icon: "image",
    tooltip: '上传图片',
    onAction: function () {
      var input = document.createElement("input");
      input.setAttribute("type", "file");
      input.setAttribute("accept", "image/*");
      input.onchange = function () {
        var file = this.files[0];
        if (file.size / 1024 / 1024 > 20) {
          failure("上传失败,图片大小请控制在 20M 以内");
        } else {
          let formData = new FormData();
          formData.append("picture", file);
          formData.append("action", "add");
          // 上传后的逻辑
          uploadImage({ formData }).then((res) => {
            var reader = new FileReader();
            reader.onload = function () {
              var id = "blobid" + new Date().getTime();
              var blobCache = tinymce.activeEditor.editorUpload.blobCache;
              var base64 = reader.result.split(",")[1];
              var blobInfo = blobCache.create(id, file, base64);
              blobCache.add(blobInfo);
              // 将图片插入到文本中
              editor.insertContent(`<img src="${blobInfo.blobUri()}"/>`);
            };
            reader.readAsDataURL(file);
          }).catch(() => {
            failure("上传出错,服务器开小差了");
          });
        }
      };
      // 触发上传
      input.click();
    },
  });
}
/**
 * @description: 一键排版
 * @param {*} editor
 * @return {*}
 */
const objLabel = {
  "h1": "title",
  "h2": "title",
  "h3": "title",
  "p": "paragraph"
}
const objStyle = {
  title: {
    "font-family": "微软雅黑",
    "font-size": "22px"
  },
  paragraph: {
    "font-size": "16px",
    "color": "red"
  }
}
export const oneClickLayout = (editor) => {
  // 参数一:自定义名称,需要放置在工具栏中
  editor.ui.registry.addButton("oneClickLayout", {
    icon: "orientation", // 显示的图标
    tooltip: '一键布局', // 提示文字
    onAction: function () {
      const doc = tinymce.activeEditor.getBody()
      doc.childNodes.forEach(item => {
        // 获取需要修改的标签
        const text = objLabel[item.localName]
        if (text) {
          // 找到对应样式循环进行配置
          for (let v in objStyle[text]) {
            item.style[v] = objStyle[text][v]
          }
        }
      })
    }
  })
}

/**
 * @description: 添加图片水印
 * @param {*} editor
 * @return {*}
 */
export const imageWatermark = (editor) => {
  editor.ui.registry.addButton("imageWatermark", {
    icon: "edit-image",
    tooltip: '添加图片水印',
    onAction: function () {
      const doc = tinymce.activeEditor.getBody()
      doc.childNodes.forEach(item => {
        const tag = item.firstChild
        // 单独修改img标签
        if (item.localName === "img" || tag.localName === "img") {
          editImages(tag)
        }
      })
    }
  })
}
/**
 * @description: 给图片添加水印
 * @param {*} child
 * @return {*}
 */
const editImages = (child) => {
  const src = child.getAttribute("src")
  var image = new Image();
  image.crossOrigin = 'anonymous';
  image.src = src;
  image.onload = async () => {
    // 创建canvas,并将创建的img绘制成canvas
    const canvas = document.createElement('canvas')
    canvas.width = child.width
    canvas.height = child.height
    const ctx = canvas.getContext('2d')
    ctx.drawImage(image, 0, 0)
    ctx.textAlign = "left"
    ctx.textBaseline = "top"
    ctx.font = "18px Microsoft Yahei"
    ctx.fillStyle = "rgba(255, 255, 255, 0.5)"
    ctx.rotate((Math.PI / 180) * 15)
    for (let i = 0; i < child.height / 120; i++) {
      for (let j = 0; j < child.width / 50; j++) {
        ctx.fillText("这是水印", i * 200, j * 100, child.width)
      }
    }
    const base64Url = canvas.toDataURL()
    setTimeout(() => {
      child.setAttribute("src", base64Url)
    }, 5000)
  }
}

Esta es una experiencia durante el uso de tinymce, y tomó mucho tiempo darse cuenta. Si tiene alguna pregunta, hable con nosotros.

Supongo que te gusta

Origin blog.csdn.net/qq_39215166/article/details/130688837
Recomendado
Clasificación