使用canvas给图片添加水印

news2024/12/23 11:08:55

上接文章“图片处理”

canvas元素其实就是一个画布,我们可以很方便地绘制一些文字、线条、图形等,它也可以将一个img标签里渲染的图片画在画布上。

我们在上传文件到后端的时候,使用input标签读取用户本地文件后得到的其实是一个Blob对象(更精确的说是File对象,特殊的Blob对象);而在页面上展示一个图片使用的是img标签;绘制功能用canvas实现。

添加水印的功能需要在img标签、canvas画布、Blob对象这三者之间相互转换,通过一些API可以完成这个工作:

我们可以从本地读取图片Blob,然后渲染到img标签,使用canvas绘制img内容并且绘制水印内容到画布,再将canvas内容转为Blob对象上传服务器,这样就完整实现了图片+水印的功能。

一、本地读取图像文件渲染到img标签

本地读取图片文件将会得到一个Blob对象,我们可以借助FileReader.readAsDataURL方法读取Blob的内容,并得到一个Base64编码的文件内容,可以将该内容赋值给img.src从而在浏览器上渲染出本地的图像。当然,img并非必须渲染到DOM树。

读取操作是个异步操作,读取完成会触发load事件,为了便于之后的调用,我们可以用一个Promise包装这个操作,最后返回一个Promise对象。

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

二、将img标签内容绘制到canvas画布

调用canvas元素画布上下文对象的drawImage方法即可实现将img内容绘制到画布。


function imgToCanvas (img) {
  let canvas = document.createElement('canvas')
  canvas.width = img.width
  canvas.height = img.height
  let ctx = canvas.getContext('2d')
  ctx.drawImage(img, 0, 0)
  return canvas
}

drawImage这个方法可以传入多个参数,以定义绘制的图像的范围,这里传入的0, 0定义从图像左上角开始绘制,后面可以继续传入两个参数来定义图像的绘制终点,不过这里整个图片都要绘制到canvas,所以采用默认值即可。

三、canvas画布上绘制水印并转换为Blob对象

在图片上传的时候,我们通常采用FormData,图片文件以一个Blob对象的形式放到FormData中,所以我们需要把canvas再转为Blob以便文件上传等操作。利用HTMLCanvasElement.toBlob方法:

function watermark (canvas, text) {
  return new Promise((resolve, reject) => {
    let ctx = canvas.getContext('2d')
    // 设置填充字号和字体,样式
    ctx.font = "24px 宋体"
    ctx.fillStyle = "#FFC82C"
    // 设置右对齐
    ctx.textAlign = 'right'
    // 在指定位置绘制文字,这里指定距离右下角20坐标的地方
    ctx.fillText(text, canvas.width - 20, canvas.height - 20)
    canvas.toBlob(blob => resolve(blob))
  })
}

四、图片添加水印完整接口

将以上三个步骤结合起来,就完整地实现了从图片添加水印,下面是一个简单的使用示例:从本地选择一个图片文件,然后添加水印后,在传入的dom元素下预览添加水印后的图片。


function imgWatermark (dom, text) {
  let input = document.createElement('input')
  input.setAttribute('type', 'file')
  input.setAttribute('accept', 'image/*')
  input.onchange = async () => {
    let img = await blobToImg(input.files[0])
    let canvas = imgToCanvas(img)
    let blob = await watermark(canvas, text)
    // 此处将Blob读取到img标签,并在dom内渲染出来;如果是上传文件,可以将blob添加到FormData中
    let newImage = await blobToImg(blob)
    dom.appendChild(newImage)
  }
  input.click()
}

给页面加一个id为container的div元素,然后如下调用:


let dom = document.querySelector('#container')
imgWatermark(dom, '水印文字')

这样就完整地给图片添加了水印效果,下面看一下实际效果。

添加水印前:

 

添加水印后(水印内容:“canvas添加的水印”):

五、总结

本文仅仅介绍了图像+水印文字的简单实现,但是涉及的一些接口其实很有用。比如有时候遇到的一个功能是头像上传的预览和剪裁,这时候你可以利用FileReader来读取文件内容预览,利用CanvasRenderingContext2D.drawImage来实现剪裁功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/563903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis7实战加面试题-基础篇(Redis持久化,Redis事务,Redis管道,Redis发布订阅)

Redis持久化 RDB (Redis DataBase) RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照。实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使…

HCIA-ARP、MAC、交换机工作原理

目录 万能数据转发模型 ARP协议:地址解析协议 以太网帧的交换 IP地址和Mac地址的区别: 以太网交换机介绍: 交换机的工作原理: ​编辑交换机处理数据的三种方式: Mac表和ARP表的区别: 万能数据转发模…

自定义注解和@Target、@Retention注解的使用

说明:注解可以理解为另一种形式的配置,可用于在类上、方法上等,标志是“”,如重写方法上的“Override”就是一种注解。这里我通过一个实例,来介绍自定义注解和java元注解(Target、Retention)的使…

案例20:Java物流管理系统设计与实现开题报告

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

ChatGPT全球最大开源平替OpenAssistant:基于Pythia和LLaMA微调而来

论文地址:https://drive.google.com/file/d/10iR5hKwFqAKhL3umx8muOWSRm7hs5FqX/view 项目地址:https://github.com/LAION-AI/Open-Assistant 数据集地址:https://huggingface.co/datasets/OpenAssistant/oasst1 体验地址:http…

Hiredis的基本使用

目录 前言 一.hiredis的安装 二.同步API 2.1.连接Redis数据库 2.1.1 无超时时间,阻塞等待连接 2.1.2 设置超时时间,阻塞等待连接。 2.1.3 非阻塞,不管连接与否,立即返回。 2.2.执行命令 2.2.1 返回执行上下文 2.2.2 没有返回执…

伪类元素的用法总结

1:自闭标签不适用伪类元素 自闭合标签 1. 一般标签   由于有开始符号和结束符号&#xff0c;因此可以在内部插入其他标签或文字。 <p>“绿叶&#xff0c;给你初恋般的感觉。”</p> 2. 自闭合标签   由于只有开始符号而没有结束符号&#xff0c;因此不可以在内…

2023-05-24:为什么要使用Redis做缓存?

2023-05-24&#xff1a;为什么要使用Redis做缓存&#xff1f; 答案2023-05-24&#xff1a; 缓存的好处 买啤酒和喝啤酒的例子可以帮助我们理解缓存的好处。 假设你在超市里买了一箱啤酒&#xff0c;如果你需要每次想喝啤酒就去超市购买&#xff0c;无疑会浪费很多时间和精力…

vue+element纯手工完美模拟实现小米有品网站

一、预览 小米有品官网&#xff1a;小米有品 本作品demo预览地址&#xff1a;点击预览 二、效果图对比 1.官方效果截图&#xff1a; 2.作者实现的demo效果图&#xff1a; 首页&#xff1a; 上新精选&#xff1a; 商品详情&#xff1a; 购物车&#xff1a; 登录&#xff1a; …

【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering(分离对比协同过滤)

【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering&#xff08;分离对比协同过滤&#xff09; 文章目录 【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering&#xff08;分离对比协同过滤&#xff09;1. 来源2. 介绍3. 模型方法3.1…

最小生成树 Prim算法实现(c语言代码)

【问题描述】 城市之间的公路交通可以用一个无向图表示。如下图所示&#xff1a; 顶点表示城市、边表示城市之间有公路相连&#xff0c;边上的权值表示城市之间的公路长度。 编程解决以下问题&#xff1a; &#xff08;1&#xff09;输入城市信息和城市之间公路的信息&…

2023最新SRC漏洞挖掘快速上手攻略!

前言 随着网络安全的快速发展&#xff0c;黑客攻击的手段也越来越多样化&#xff0c;因此SRC漏洞挖掘作为一种新的网络安全技术&#xff0c;也在不断发展和完善。那么&#xff0c;作为一个网安小白如果想要入门SRC漏洞挖掘&#xff0c;需要掌握哪些知识呢&#xff1f;以下是本…

Vue3入门

前言 在Vue 3提供的丰富的基础配置和插件生态系统之下&#xff0c;它是一种适用于多场景开发的前端框架&#xff0c;包括web应用程序、移动应用和桌面应用。使用Vue 3&#xff0c;您可以快速高效构建出具有优秀用户体验的应用程序。 准备工作 首先&#xff0c;我们需要安装V…

运营-15.涉及促销活动的计算原则

1.是否 参与促销活动 如果商品参加促销活动&#xff0c;则在订单结算的时候显示已经参加的活动&#xff0c;否 则不显示&#xff1b; 2.是否 满足促销条件 如果有参加某个活动&#xff0c;则还要判断是否满足活动的条件&#xff0c;比如满200减 10&#xff0c;但是商品价格不足…

spring-cloud-alibaba-seata分布式事务实例

第一步: 首先访问: https://seata.io/zh-cn/blog/download.html 下载我们需要使用的seata1.6.0服务 第二步: 1.在你的参与全局事务的数据库中加入undo_log这张表 -- for AT mode you must to init this sql for you business database. the seata server not need it. CRE…

关于档案室十防环境监控的一些关键内容

档案库房十防监控系统 智慧档案平台/温湿度/空气质量/漏水/视频/门禁/一体化管控平台 HONSOR多维空间可视化智慧档案库房建设一体化平台分享 三维可视化智慧档案馆库房一体化环境安全管控系统平台【相关项目经验图片/相关系统拓展图】【鉴赏】 1、智慧档案馆 2、智慧档案库房…

从零开始之电机FOC控制

我们将撕开FOC神秘而虚伪的面纱&#xff0c;以说人话的方式讲述它。真正的做到从零开始&#xff0c;小白一看就会&#xff0c;一学就废。 如果觉得有用的话&#xff0c;就点个赞呗&#xff0c;纯手码。 一、什么是FOC&#xff1f; FOC是Field Orientation Control的缩写&#…

2023年,千万别裸辞....

作为IT行业的大热岗位——软件测试&#xff0c;只要你付出了&#xff0c;就会有回报。说它作为IT热门岗位之一是完全不虚的。可能很多人回说软件测试是吃青春饭的&#xff0c;但放眼望去&#xff0c;哪个工作不是这样的呢&#xff1f;会有哪家公司愿意养一些闲人呢&#xff1f;…

GaussDB云数据库SQL应用系列-基础使用

目录 一、前言 二、前提条件 1、连接数据库实例 2、GaussDB实例正常运行 三、操作示例 1、选择实例并进入SQL执行界面 2、创建数据库用户 3、创建数据库 4、创建SCHEMA 5、创建表&#xff08;增删改查&#xff09; 1&#xff09;创建3张表&#xff0c;并初始化一些数…

Revit技巧 | 楼梯总画不好?原来是这些技巧你没有掌握

Revit技巧 | 楼梯总画不好&#xff1f;原来是这些技巧你没有掌握 楼梯在我们BIM考试中是重点和难点&#xff0c;根据我们对历年考考题的分析&#xff0c;楼梯部分涉及到的考点为&#xff1a; 栏杆扶手样式的设置&#xff1b; 楼梯踏步数的设置&#xff1b; 楼梯踏板宽度的设…