掘金编辑器的直接粘贴图片

78 阅读2分钟

这是我的第二篇文章,第一次用掘金写文章的时候我发现掘金编辑器可以直接粘贴图片到编辑器里面很神奇

总体实现思路应该是

  • 监听粘贴事件,判断是否是图片
  • 给图片上传水印
  • 上传返回图片路径

监听粘贴事件并判断是图片

前两天看到一个文章他是这样监听粘贴事件的

document.addEventListener("paste", async (event) => {
      let items = event.clipboardData && event.clipboardData.items;
      if (items && items.length) {
        // 检索剪切板items
        for (let i = 0; i < items.length; i++) {
          if (items[i].type.indexOf("image") !== -1) {
            let file = items[i].getAsFile();
            获取到图片内容
          }
        }
      }
    });

这是粘贴事件打印出来的,我们要的数据存在clipboardData里面,这是一个DataTransfer类型的数据

  • 这边发现如果同时粘贴两张图片类型就变成text/plain,不能进入判断,掘金的编辑器也不能同时粘贴两张图片
  • 如果不判断类型可以直接使用 clipboardData.getData("text/plain"), 获取剪切板的内容,如果是图片会返回base64

1700126453914.png

图片加水印

export default class ImgWithWaterMark {
    constructor(options) {
        options = options || {}
        this.canvas = null
        this.fillStyle = options.fillStyle || '#fff'
        this.text = options.text || ''
        this.quality = options.quality || 0.5
    }
    createDom() {
        this.canvas = document.createElement('canvas')
    }
    getImgInfo(img) {
        return new Promise((resolve, reject) => {
            let reader = new FileReader()
            reader.onload = function (result) {
                let image = new Image()
                image.src = result.target.result
                image.onload = function () {
                    resolve({ width: this.width, height: this.height, image: this })
                }
            }
            reader.readAsDataURL(img)
        })
    }
    setWaterMark({ img, text }) {
        return new Promise(async (resolve) => {
            if (text) {
                this.text = text
            }
            if (!this.context) {
                this.createDom()
            }
            let context = this.canvas.getContext('2d')
            const { width, height, image } = await this.getImgInfo(img)
            context.reset()
            context.restore();
            this.canvas.width = width
            this.canvas.height = height
            context.font = `bold ${width / 20}px serif`;
            context.fillStyle = this.fillStyle
            context.drawImage(image, 0, 0, width, height)
            const textMetrics = context.measureText(this.text)
            const textWidth = textMetrics.actualBoundingBoxLeft + textMetrics.actualBoundingBoxRight
            const textHeight = textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent
            context.fillText(text, width - textWidth, height - textHeight)
            let res = this.canvas.toDataURL("image/jpeg", this.quality)
            resolve(res)
        })

    }
    destoryCanvas() {
        this.canvas = null
    }
}

完整代码

    document.addEventListener("paste", async (event) => {
      let clipboardData = event.clipboardData || {};
      let items = clipboardData.items || [];
      if (items && items.length) {
        // 检索剪切板items
        for (var i = 0; i < items.length; i++) {
          if (items[i].type.indexOf("image") !== -1) {
            let file = items[i].getAsFile();
            // 获取到图片内容;
            let img = await that.imgWithWaterMark.setWaterMark({
              img: file,
              text: "你的水印内容",
            });
            //上传图片 img返回base64具体怎么传参可以跟后端沟通之后让他返回图片链接大概就可以模拟掘金编辑器的粘贴图片了
            break;
          }
        }
      }
    });