js上传图片时添加水印

本文介绍了在Vue项目中如何利用原生canvas和html2canvas库为上传图片添加水印。详细讲解了两种实现方式的步骤,包括图片转为DOM元素、在canvas上画水印和文本、最后转回File对象上传。原生canvas实现更繁琐,但灵活性高,html2canvas则简化了流程,适合复杂水印需求。在实际应用中,可以根据需求选择合适的方法。
摘要由CSDN通过智能技术生成

前言

在实际业务开发中,经常会遇到上传图片时要添加上自己网站水印,这个水印各种类型都有,这里主要讲下我在开发中,客户的需要在上传图片时添加上当前录入表单的一些信息,方便后期直接查看图片追溯信息。先放下最终实现的上传成功后缩略图和预览图:
在这里插入图片描述
在这里插入图片描述

实现该功能主要有2种:原生的canvas实现和使用html2canvas库。当前项目是基于element-ui的一个vue项目,提供思路,代码仅供参考。

原生的canvas

其思路就是File对象–>img DOM元素–>转为canvas–>画水印图片–>画文本–>转为blob–>转为File对象(后端上传需要File对象)–>调用接口上传给服务器

1、获取File对象,并转为DOM元素

element的上传组件自带回调函数里可以获取到当前上传文件的file对象,里面的file.raw就是我们要的File对象,代码如下:

// file为element的上传组件自带回调函数里的一个文件对象
file2Img(file) {
    return new Promise((resolve, reject) => {
        let img = new Image()
        img.src = URL.createObjectURL(file.raw)
        img.addEventListener('load', () => resolve(img))
    })
}
2、DOM元素转为canvas对象
img2Canvas(img) {
    const canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    const ctx = canvas.getContext('2d')
    ctx.drawImage(img, 0, 0)
    return canvas
},
3、canvas对象里画水印背景图
// y是画图片的y轴定位坐标
drawWatermark(ctx, y) {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = require('@/assets/images/watermark-bg.png')
        img.addEventListener('load', () => {
            ctx.drawImage(img, 0, y)
            console.log(img)
            resolve()
        })
    })
},
4、canvas对象里画文本
drawText(ctx, y) {
    // 设置填充字号和字体,样式
    ctx.font = '16px 宋体 bold'
    ctx.fillStyle = 'rgba(255, 255, 255)'
    // 设置左对齐
    ctx.textAlign = 'left'
    ctx.fillText('昭通高速巧家收费站', 100, y + 40)

    ctx.fillStyle = 'rgba(0, 0, 0)'
    ctx.fillText('巡查内容:日巡查', 10, y + 86)
},
5、canvas对象转为blob对象
canvas2Blob(canvas) {
    return new Promise((resolve, reject) => {
        canvas.toBlob(blob => resolve(blob))
    })
},
6、最后通过调用上面的方法在上传前处理下文件即可
// file为element的上传组件自带回调函数里的一个文件对象
async addWatermark(file) {
    // 把上传的图片转为img dom对象
    const img = await this.file2Img(file)
    // 把图片画在canvas上,并返回canvas对象
    const canvas = this.img2Canvas(img)
    const ctx = canvas.getContext('2d')
    // 高度是根据固定的水印图片高度计算
    const y = canvas.height - 240
    // canvas上画水印图片
    await this.drawWatermark(ctx, y)
    // canvas上画文本
    this.drawText(ctx, y)
    // 转为blob对象
    const blob = await this.canvas2Blob(canvas)
    // 转为后端要的file对象
    const newFile = new File([blob], file.name, { type: file.raw.type })
    return newFile
}

html2canvas库

使用该库思路较为简单,就是把上传的图片作为背景图(html2canvas不能画背景图,这里用img标签替换),把水印通过html+css方式写在背景图上,然后用html2canvas来把html转化为canvas对象,再把canvas对象转为blob对象,最后转为File对象传给后端。

// html和css省略,主要就是写了一个以上传图片为背景,加上水印样式的dom
import html2canvas from 'html2canvas'

async addWatermark(file) {
    // 获取用img标签代替背景图的img DOM元素
    const uploadImg = document.querySelector('#uploadImg')

    // file为element的上传组件自带回调函数里的一个文件对象,file.raw是上传文件的File对象,img显示当前上传图片
    uploadImg.src = URL.createObjectURL(file.raw)

    // document.querySelector('#capture')获取需要转为canvas的dom节点
    const canvas = await html2canvas(document.querySelector('#capture'))

    // 转为blob对象
    const blob = await this.canvas2Blob(canvas)
    
    // 转为后端要的file对象
    const newFile = new File([blob], file.name, { type: file.raw.type })
    return newFile
}
注意:html2canvas库绘制的DOM必须是可见的,但是实际项目中,用于转为canvas的这个DOM用户是不可见的,简单的方式就是通过css的定位属性,把这个DOM片段定位出浏览器视图外面。

优缺点

从代码里可以看出,原生canvas步骤比较繁琐,且很死板,添加的水印背景图还需要固定大小,那么里面的文字如果是不定的,很容易溢出背景图。而用html2canvas库就没这个顾虑,毕竟写css样式很灵活。但是这个库体量还是较大的,压缩后还有46kb,而且有冗余DOM。所以建议简单水印可用原生canvas,相对复杂的再用这个库。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值