Skip to content

修改自定义图片大小

效果

流程

注意

  1. 设置弹出弹出框 写好点击事件

  2. 绑定到菜单

  3. 修改 editorConfig 加入自定义宽高

代码

注意

  1. 必须使用 @ts-ignore 忽略掉细节

  2. 重点看 ImageSize

  3. MyMenu 就是插入图片

vue
<template>
  <div style="border: 1px solid #ccc">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      style="height: 500px; overflow-y: hidden"
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="handleCreated"
    />
    <el-button type="primary" @click="getcontent">获取内容</el-button>
  </div>
</template>

<script setup lang="ts">
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { onBeforeUnmount, ref, shallowRef, onMounted, watch } from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { SlateTransforms, SlateElement } from "@wangeditor/editor";
// 1. 引入boot
import { Boot } from "@wangeditor/editor";
// 设置内容
const props = defineProps({
  html: {
    type: String,
    default: "",
  },
});
watch(
  () => {
    return props.html;
  },
  () => {
    valueHtml.value = props.html;
  }
);
// 编辑器实例,必须用shallowRef包裹

const editorRef = shallowRef();

// 内容HTML

const valueHtml = ref("");

// 编辑器模式

const mode = ref("default"); // simple或者default;

// 模拟ajax异步获取数据内容

onMounted(() => {});

// 编辑器配置

const editorConfig = {
  placeholder: "请输入内容...",
  hoverbarKeys: {
    image: {
      menuKeys: [
        "imageWidth30",
        "imageWidth50",
        "imageWidth100",
        "imageSize",
        "editImage",
        "viewImageLink",
        "deleteImage",
      ],
    },
  },
};

// 组件销毁的时候,也即时 销毁编辑器

onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

// 编辑器示例

const handleCreated = (editor) => {
  editorRef.value = editor; // 记录editor实例
};

// 获取到编辑器内容

const getcontent = () => {
  console.log(valueHtml.value);
};
// 自定义节点
class MyMenu {
  public title = "";

  public tag = "";

  public iconSvg = "";

  constructor() {
    // 自定义菜单标题

    this.title = "自定义按钮";

    // 类型

    this.tag = "button";

    // 自定义菜单图标

    this.iconSvg =
      '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" t="1687315735883" class="icon" viewBox="0 0 1024 1024" version="1.1" p-id="13367" width="16" height="16" style="color:white;"><path stroke="#ff0000" fill="#ff0000" d="M890.88 63.488q28.672 0 52.736 10.752t41.984 29.184 28.16 43.52 10.24 53.76l0 620.544q0 28.672-10.24 53.76t-28.16 43.52-41.984 29.184-52.736 10.752l-689.152 0q-28.672 0-53.76-10.752t-43.52-29.184-29.184-43.52-10.752-53.76l0-620.544q0-28.672 10.752-53.76t29.184-43.52 43.52-29.184 53.76-10.752l689.152 0zM256 254.976q9.216 0 27.648 0.512t43.008 0.512l52.224 0 55.296 0q64.512 0 141.312-1.024l0-63.488-126.976 0 0-64.512-64.512 0 0 64.512-128 0 0 63.488zM377.856 360.448q-8.192-15.36-15.36-29.696-6.144-12.288-12.288-25.088t-9.216-20.992l-58.368 21.504 32.768 76.8zM254.976 756.736l101.376-143.36-66.56-26.624-98.304 145.408zM448.512 574.464l126.976 0 0-62.464-45.056 0-81.92 0 0-64.512q23.552 0 46.08 0.512t40.96 0.512l40.96 0 0-63.488-66.56 0q-19.456 0-40.96-1.024l68.608-65.536-68.608-32.768-20.48 98.304-257.024 0 0 63.488 35.84 0 47.104 0 53.248 0 56.32 0 0 64.512-128 0 0 62.464 40.96 0q18.432 0 40.96 0.512t46.08-0.512l0 129.024q0 16.384-2.048 27.136t-10.24 15.36-25.088 4.608-47.616-5.12q25.6 31.744 27.648 71.68 13.312-2.048 34.304-1.024t40.448-1.536 33.28-12.8 13.824-34.816l0-192.512zM568.32 685.056q-16.384-19.456-29.696-37.888-11.264-15.36-23.552-30.208t-18.432-23.04l-46.08 30.72 64.512 98.304zM896 379.904q-20.48-1.024-53.248-0.512t-63.488 1.536q-36.864 1.024-75.776 3.072l0-129.024q49.152 0 85.504-4.608t59.904-9.728q27.648-6.144 46.08-14.336-18.432-27.648-29.696-46.08-5.12-8.192-9.728-15.36t-7.68-11.264-3.584-4.608 1.536 4.608q-21.504 16.384-57.344 24.064t-69.632 10.752-57.344 3.072-21.504 0q1.024 16.384 1.536 44.032t0 77.824-1.024 129.024-0.512 196.608q0 13.312-3.072 33.28t-10.24 39.936-19.968 35.328-31.232 19.456q12.288 3.072 21.504 11.776t16.896 18.432 13.824 19.456 12.288 14.848q12.288-18.432 23.552-42.496t20.48-50.176 14.336-52.224 5.12-47.616l0-40.96 0-43.008 0-47.104 0-60.416 64.512 0 0 384 63.488 0 0-384q23.552 1.024 35.328 0.512t29.184 3.584l0-71.68z" p-id="13368"></path></svg>';
  }

  // 获取菜单执行时的value,用不到则返回空,字符串或者false

  getValue(editor) {
    console.log(editor);
    return "自定义按钮";
  }

  // 菜单是否需要激活(如选中加粗文本,"加粗"菜单会激活) 用不到则返回 false

  isActive(editor) {
    return false; // or true
  }

  // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false

  isDisabled(editor) {
    return false; // or true
  }

  // 点击菜单出发的函数
  exec(editor, value) {
    // 插入文本
    // editor.insertText(value); // value 即 this.getValue(editor) 的返回值
    // 插入对话框
    // modalflag.value = true;
    // 插入节点
    const resulttext =
      '<p><img src="https://dianyuan-public.oss-cn-shenzhen.aliyuncs.com/static/live/color_avatar/2.png"></p>';
    editor.dangerouslyInsertHtml(resulttext);
  }
}
const myMenuConf = {
  key: "myMenu",
  factory() {
    return new MyMenu();
  },
};

// 自定义节点
class imageSize {
  public title = "";

  public tag = "";

  public iconSvg = "";

  constructor() {
    // 自定义菜单标题

    this.title = "自定义按钮";

    // 类型

    this.tag = "button";

    // 自定义菜单图标

    this.iconSvg =
      '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" t="1687315735883" class="icon" viewBox="0 0 1024 1024" version="1.1" p-id="13367" width="16" height="16" style="color:white;"><path stroke="#ff0000" fill="#ff0000" d="M890.88 63.488q28.672 0 52.736 10.752t41.984 29.184 28.16 43.52 10.24 53.76l0 620.544q0 28.672-10.24 53.76t-28.16 43.52-41.984 29.184-52.736 10.752l-689.152 0q-28.672 0-53.76-10.752t-43.52-29.184-29.184-43.52-10.752-53.76l0-620.544q0-28.672 10.752-53.76t29.184-43.52 43.52-29.184 53.76-10.752l689.152 0zM256 254.976q9.216 0 27.648 0.512t43.008 0.512l52.224 0 55.296 0q64.512 0 141.312-1.024l0-63.488-126.976 0 0-64.512-64.512 0 0 64.512-128 0 0 63.488zM377.856 360.448q-8.192-15.36-15.36-29.696-6.144-12.288-12.288-25.088t-9.216-20.992l-58.368 21.504 32.768 76.8zM254.976 756.736l101.376-143.36-66.56-26.624-98.304 145.408zM448.512 574.464l126.976 0 0-62.464-45.056 0-81.92 0 0-64.512q23.552 0 46.08 0.512t40.96 0.512l40.96 0 0-63.488-66.56 0q-19.456 0-40.96-1.024l68.608-65.536-68.608-32.768-20.48 98.304-257.024 0 0 63.488 35.84 0 47.104 0 53.248 0 56.32 0 0 64.512-128 0 0 62.464 40.96 0q18.432 0 40.96 0.512t46.08-0.512l0 129.024q0 16.384-2.048 27.136t-10.24 15.36-25.088 4.608-47.616-5.12q25.6 31.744 27.648 71.68 13.312-2.048 34.304-1.024t40.448-1.536 33.28-12.8 13.824-34.816l0-192.512zM568.32 685.056q-16.384-19.456-29.696-37.888-11.264-15.36-23.552-30.208t-18.432-23.04l-46.08 30.72 64.512 98.304zM896 379.904q-20.48-1.024-53.248-0.512t-63.488 1.536q-36.864 1.024-75.776 3.072l0-129.024q49.152 0 85.504-4.608t59.904-9.728q27.648-6.144 46.08-14.336-18.432-27.648-29.696-46.08-5.12-8.192-9.728-15.36t-7.68-11.264-3.584-4.608 1.536 4.608q-21.504 16.384-57.344 24.064t-69.632 10.752-57.344 3.072-21.504 0q1.024 16.384 1.536 44.032t0 77.824-1.024 129.024-0.512 196.608q0 13.312-3.072 33.28t-10.24 39.936-19.968 35.328-31.232 19.456q12.288 3.072 21.504 11.776t16.896 18.432 13.824 19.456 12.288 14.848q12.288-18.432 23.552-42.496t20.48-50.176 14.336-52.224 5.12-47.616l0-40.96 0-43.008 0-47.104 0-60.416 64.512 0 0 384 63.488 0 0-384q23.552 1.024 35.328 0.512t29.184 3.584l0-71.68z" p-id="13368"></path></svg>';
    // @ts-ignore
    this.showModal = true; // 没有他就不会有弹出层
    // @ts-ignore
    this.modalWidth = 400;
    // @ts-ignore
    this.modalHeight = 500;
  }

  // 获取菜单执行时的value,用不到则返回空,字符串或者false

  getValue(editor) {
    console.log(editor);
    return "自定义按钮";
  }

  // 菜单是否需要激活(如选中加粗文本,"加粗"菜单会激活) 用不到则返回 false

  isActive(editor) {
    return false; // or true
  }

  // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false

  isDisabled(editor) {
    return false; // or true
  }

  // 点击菜单出发的函数
  exec(editor, value) {}
  getModalPositionNode(editor) {
    return null; // modal 依据选区定位
  }
  // 定义 modal 内部的 DOM Element
  getModalContentElem(editor) {
    const content = document.createElement("div");
    content.innerHTML = `
          <form>
            <div style="display: flex;align-items: center;">
              宽度:<input id="width" placeholder="宽度" style="width: 180px;height: 30px;text-indent: 10px;" />&nbsp;px
            </div>
            <div style="display: flex;align-items: center;margin-top:20px;">
              高度:<input id="height" placeholder="高度" style="width: 180px;height: 30px;text-indent: 10px;" />&nbsp;px
            </div>
          </form>
        `;
    const button = document.createElement("span");
    button.style.padding = "5px 10px";
    button.style.border = "1px solid #ccc";
    button.style.borderRadius = "5px";
    button.style.cursor = "pointer";
    button.style.marginTop = "20px";
    button.style.marginBottom = "20px";
    button.style.backgroundColor = "#409eff";
    button.style.color = "#fff";
    button.style.display = "inline-block";
    button.innerHTML = "确定";
    content.appendChild(button);
    button.onclick = () => {
      // @ts-ignore
      const width = content.querySelector("#width").value;
      // @ts-ignore
      const height = content.querySelector("#height").value;
      // 选中图片父节点
      editor.restoreSelection();
      // 设置宽高
      SlateTransforms.setNodes(
        editor,
        {
          // @ts-ignore
          style: {
            width: `${width}px`,
            height: `${height}px`,
          },
        },
        {
          // 添加match否则样式添加到图片父节点上
          match: (node) => {
            // @ts-ignore
            if (SlateElement.isElement(node)) {
              // @ts-ignore
              if (node.type === "image") {
                return true; // 匹配 image
              }
            }
            return false;
          },
        }
      );
    };
    return content;
  }
}
const imageSizeConfig = {
  key: "imageSize",
  factory() {
    return new imageSize();
  },
};

// 工具栏配置

const toolbarConfig = {
  insertKeys:
    // {
    //     index: 0, // 插入的位置,基于当前的 toolbarKeys 如果多个就是
    //     keys: ['myMenu','imageSize']
    // },
    {
      index: 0, // 插入的位置,基于当前的 toolbarKeys
      keys: ["myMenu"],
    },
};

// 这里必须要判断一下 避免重复注册
if (Boot.plugins.length < 13) {
  Boot.registerMenu(myMenuConf);
  Boot.registerMenu(imageSizeConfig);
}

defineExpose({
  getcontent,
});
</script>

<style scoped lang="scss"></style>