当前位置: 首页 > news >正文

JS VUE 用 canvas 给图片加水印

最近写需求,遇到要给图片加水印的需求。 刚开始想的方案是给图片上覆盖一层水印照片,但是这样的话用户直接下载图片水印也会消失。
后来查资料发现用 canvas 就可以给图片加水印,下面是处理过程。

请添加图片描述
首先我们要确认图片的格式,我们通过 input 上传的图片格式一般是 File (File 对象是特殊类型的 Blob)即 Blob 格式。
这样的话,我们需要先把 Blob 文件转成 img 标签,先通过 FileReader 读取文件,通过 reader.readAsDataURL 获得文件 Base 64 编码 URL 地址,拿到 URL 后,生成 img 标签。

1. Blob 文件转成 img 标签

	// blob 文件格式转成 img 标签const blobToImg = (blob) => {return new Promise((resolve, reject) => {const reader = new FileReader()reader.readAsDataURL(blob)reader.onload = () => {let img = new Image()img.src = reader.resultimg.addEventListener('load', () => resolve(img))}})}

这里要注意,如果使用 addEventListener 需要先注册事件监听。

const blobToImg = (blob) => {return new Promise((resolve, reject) => {const reader = new FileReader()reader.addEventListener('load', () => {let img = new Image()img.src = reader.resultimg.addEventListener('load', () => resolve(img))})reader.readAsDataURL(blob)})}

2. img 标签转成 canvas

 // 将img内容绘制到canvas画布imgToCanvas(img) {const canvas = document.createElement('canvas')canvas.width = img.widthcanvas.height = img.heightconst context = canvas.getContext('2d')context.drawImage(img, 0, 0)return canvas}

3. 在 canvas 画布上绘制水印

水印通过 ctx.createPattern(image, repetition) 方法来进行重复绘制,由于 image 参数要是是 img 标签格式或者 canvas 文件格式,所以我们可以让 UI 老师生成一个水印的图片,或者我们用 canvas 自己画一个水印的图片进行复制。

如果我们需要直接生成图片来进行展示,那我们可以用 canvas.toDataURL() 直接从 canvas 生成图片地址。
如果需要生成 Blob 格式传给后端,那我们可以用 canvas.toBlob() 方法从 canvas 生成 Blob 文件格式,传给后端。

    // canvas画布上绘制水印waterMark(canvas) {return new Promise((resolve, reject) => {const ctx = canvas.getContext('2d')// 绘制水印 canvasconst canvasWater = this.drawWaterCanvas('已失效')// 绘制重复的水印ctx.fillStyle = ctx.createPattern(canvasWater, 'repeat')ctx.fillRect(0, 0, canvas.width, canvas.height)// 这里我需要直接展示,所以就直接生成图片地址resolve(canvas.toDataURL())})},drawWaterCanvas(str) {const canvasWater = document.createElement('canvas')canvasWater.width = 400canvasWater.height = 400const ctxWater = canvasWater.getContext('2d')ctxWater.textAlign = 'left'ctxWater.textBaseline = 'middle'ctxWater.font = '32px Microsoft Yahei'ctxWater.fillStyle = 'rgba(0, 0, 0, 0.3)'ctxWater.rotate((-20 * Math.PI) / 180)ctxWater.fillText(str, 10, 80)return canvasWater}

4. VUE 中实际应用

<template><div><img :src="imgUrl" alt="" /></div>
</template><script>
import loppy from './assets/loppy.jpg'export default {data() {return {imgUrl: ''}},created() {const img = new Image()img.src = loppyimg.onload = async () => {const canvas = this.imgToCanvas(img)const url = await this.waterMark(canvas)this.imgUrl = url}},methods: {// 将img内容绘制到canvas画布imgToCanvas(img) {const canvas = document.createElement('canvas')canvas.width = img.widthcanvas.height = img.heightconst context = canvas.getContext('2d')context.drawImage(img, 0, 0)return canvas},// canvas画布上绘制水印并转换为blob对象waterMark(canvas) {return new Promise((resolve) => {const ctx = canvas.getContext('2d')// 绘制水印 canvasconst canvasWater = this.drawWaterCanvas('图片已失效')// 绘制重复的水印ctx.fillStyle = ctx.createPattern(canvasWater, 'repeat')ctx.fillRect(0, 0, canvas.width, canvas.height)resolve(canvas.toDataURL())})},drawWaterCanvas(str) {const canvasWater = document.createElement('canvas')canvasWater.width = 500canvasWater.height = 500const ctxWater = canvasWater.getContext('2d')ctxWater.textAlign = 'left'ctxWater.textBaseline = 'middle'ctxWater.font = '32px Microsoft Yahei'ctxWater.fillStyle = 'rgba(0, 0, 0, 0.3)'ctxWater.rotate((-20 * Math.PI) / 180)ctxWater.fillText(str, 10, 200)ctxWater.fillText(new Date().toLocaleString(), 10, 300)return canvasWater}}
}
</script><style lang="scss" scoped>
img {width: 200px;height: 200px;
}
</style>

在这里插入图片描述

http://www.lryc.cn/news/190406.html

相关文章:

  • 主动配电网故障恢复的重构与孤岛划分matlab程序
  • 2023C语言暑假作业day6
  • java try 自动关闭流
  • WebDAV之π-Disk派盘 + 元思笔记
  • electron自定义标题栏,并监听双击以及右键改变窗口大小。
  • Beam Focusing for Near-Field Multi-User MIMO Communications阅读笔记
  • Unity基础课程之物理引擎6-关于物理材质的使用和理解
  • 用c语言写一个剪刀石头布小游戏
  • 【MySQL入门到精通-黑马程序员】MySQL基础篇-DCL
  • SpringBoot配置文件加载顺序
  • github小记(一):清除github在add或者commit之后缓存区
  • 【Debian系统】:安装debian系统之后,很多命令找不到,需要添加sudo之后才能使用,以下解决方法
  • 深入了解归并排序:原理、性能分析与 Java 实现
  • docker stop了一个docker exec容器,要怎么再启动呢
  • 【总结】kubernates 插件工具总结
  • RK3588平台产测之ArmSoM-W3 DDR带宽监控
  • 基于SpringBoot的作业管理系统设计与实现
  • TailwindCss Functions Directives
  • MDK自动生成带校验带SVN版本号的升级文件
  • 如何打造一个网络框架模块对接服务器
  • 装饰器模式和 AOP 面向切片编程(设计模式与开发实践 P15)
  • Git迁移新仓库并保存历史提交记录
  • MySql逗号分割的字段数据分解为多行
  • 共生与共享:线程与进程的关系
  • uniapp app或微信小程序项目使用gite仓库中的图片
  • KUKA机器人如何强制输出或取消数字IO信号?
  • 利用正则表达式进行数据采集和处理
  • javaScript:拖拽效果
  • 【Unity3D编辑器开发】Unity3D中制作一个可以随时查看键盘对应KeyCode值面板,方便开发
  • VUE echarts 柱状图、折线图 双Y轴 显示