JS VUE 用 canvas 给图片加水印

news/2024/7/10 3:01:43 标签: 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.result
          img.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.result
          img.addEventListener('load', () => resolve(img))
        })
        reader.readAsDataURL(blob)
      })
    }

canvas_38">2. img 标签转成 canvas

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

canvas__52">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')
        // 绘制水印 canvas
        const 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 = 400
      canvasWater.height = 400
      const 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 = loppy
    img.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.width
      canvas.height = img.height
      const context = canvas.getContext('2d')
      context.drawImage(img, 0, 0)
      return canvas
    },
    // canvas画布上绘制水印并转换为blob对象
    waterMark(canvas) {
      return new Promise((resolve) => {
        const ctx = canvas.getContext('2d')
        // 绘制水印 canvas
        const 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 = 500
      canvasWater.height = 500
      const 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.niftyadmin.cn/n/5084043.html

相关文章

软件设计师学习笔记12-数据库的基本概念+数据库的设计过程+概念设计+逻辑设计

1.数据库的基本概念 1.1数据库的体系结构 1.1.1常见数据库 ①集中式数据库 数据是集中的&#xff1b;数据管理是集中的 ②C/S结构 客户端负责数据表服务&#xff1b;服务器负责数据库服务&#xff1b;系统分前后端&#xff1b;ODBC、JDBC ③分布式数据库 物理上分布、逻…

如何看待为了省小钱而花费时间

相信每个人都会遇到这种情况&#xff1a;购买东西时想着货比三家或者想办法领优惠券、凑单等就可以省下一些钱&#xff0c;但是需要花费不少时间和精力。这时就开始犹豫了&#xff1a;省钱是必要的&#xff0c;需要居安思危&#xff0c;等到缺钱的时候不会后悔&#xff1b;又想…

二、BurpSuite Proxy代理

一、配置与基础 配置&#xff1a;配置代理的端口 Forward&#xff1a;将拦截的请求正常发往服务器 Drop&#xff1a;直接将请求丢弃 intercept&#xff1a;开启后才能进行请求拦截 Open brower&#xff1a;在2021版本之后&#xff0c;点击该选项即可开启BurpSuite自带的浏览器…

Kafka数据同步原理详解

Kafka数据同步原理详解 Kafka是一种分布式的消息队列系统&#xff0c;它具有高吞吐量、可扩展性和分布式特性等优势。在Kafka中&#xff0c;数据按照主题进行分区&#xff0c;每个主题都有一组分区。每个分区都有自己的生产者和消费者&#xff0c;生产者负责向分区中写入消息&…

iMazing2023免费版苹果iPhone手机备份应用软件

iMazing是一款功能强大的苹果手机备份软件&#xff0c;它可通过备份功能将通讯录备份到电脑上&#xff0c;并在电脑端iMazing“通讯录”功能中随时查看和导出联系人信息。它自带Wi-Fi自动备份功能&#xff0c;能够保证通讯录备份数据是一直在动态更新的&#xff0c;防止手机中新…

必知必会的22种设计模式(GO语言)

日常工作中免不了使用设计模式&#xff0c;那么你使用了哪些设计模式呢&#xff1f; 设计模式是什么&#xff1f; 设计模式是一种在软件设计中对常见问题的通用解决方案。 它们是经过验证的、可重用的设计思想&#xff0c;可以帮助解决开发过程中遇到的各种问题。 设计模式…

UM Company区块链游戏登场全球 元宇宙场景再获国际关注

知情人士透露&#xff0c;UM Company在泰国是以数字化创新、大数据、物联网、人工智能、区块链、元宇宙等新一代信息技术服务的创新型企业。 2023年开始&#xff0c;UM Company积极推进全球区块链业务&#xff0c;全面带企业在全球领域市场的占比份额。早在今年5月份&#xff0…

【技术干货】如何快速创建商用照明 OEM APP?

本文介绍了如何在涂鸦 IoT 平台的 App 工作台上创建一款体验版商照 App、正式版 OEM App、上架 App、以及完成通用配置。 OEM App 开发 创建 App 登录 涂鸦 IoT 平台的 App 页面。 单击 创建APP&#xff0c;选择 商照 APP 进行创建。 在提示框里&#xff0c;完善 App 信息…