利用canvas给图片添加水印

news2024/11/28 0:56:33

前言


前两天给个人网站添加了一个小功能,就是在文章编辑上传图片的时候自动给图片加上水印。给网页图片添加水印是个常见的功能,也是互联网内容作者保护自己版权的方法之一。本文简单记录一下借助canvas在前端实现图片添加水印的实现方法。

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, '水印文字')

这样就完整地给图片添加了水印效果,下面看一下实际效果,你也可以在线体验。

添加水印前:

添加水印后(水印内容:“腾冲·清凉山”):

五、总结


本文仅仅介绍了图像+水印文字的简单实现,但是涉及的一些接口其实很有用。比如有时候遇到的一个功能是头像上传的预览和剪裁,这时候你可以利用FileReader来读取文件内容预览,利用CanvasRenderingContext2D.drawImage来实现剪裁功能。关于本文接口的更多详细用法,可以参照MDN文档,文章中的api都使用了链接的形式链接到了MDN。

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

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

相关文章

学python的第七天---基础进阶

一、数组翻转写法一:myselfa[:size]a[:size][::-1]写法二:函数写法三:二、复制数组写法一:写法二:写法三:三、最小公倍数写法一:写法二:写法三:gcd写法四:其他&#xff1…

visual studio 2019创建一个项目的详细步骤

引言:本着边学边记录的原则,把学习的过程给记录下来,自己回顾的同时也分享给大家,转载请注明出处哈。 1、首先在桌面上双击打开visual studio 2019,看到如下界面: 2、点击1红框中的创建新项目,…

[hive]执行计划

https://www.bilibili.com/video/BV1g84y147sX/?p126&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source51f694f71c083955be7443b1d75165e0一、概述Explain呈现的执行计划,由一系列Stage组成,这一系列Stage具有依赖关…

Easy Deep Learning——全连接层

什么是全连接层?它的作用是什么? 我们还是回到之前的草地场景中,假设现在的问题变成让机器判断该草地上是不是有一只猫存在,由于之前做的卷积操作,将草地分成了许多网格,如果场地上只有一只猫,那么只有一个网格是有猫的,而其他的网格都不存在猫,一个卷积核运算可以得到…

java-泛型介绍

介绍 泛型是jdk5的时候出现的一种特性,可以在编译阶段约束操作的数据结构,并进行检查。 泛型只能用引用数据类型,如果是基本数据类型得使用包装类。 如ArrayList中的toArray(T[] a),是不可用转换为int[]的只能转换为Integer[] 好处 统一了…

Mysql的数据存储

Mysql的数据存储 对于mysql而言,数据是存储在文件系统中的,不同的存储存储引擎会有不同的文件格式和组织形式 1、InnoDB数据存储 InnoDB存储格式由大到小:表空间 → 段 → 区 → 页 → 行 对于innodb而言,数据是存储在表空间&…

linux系统整理一些工作中常用关于用户,用户组以及文件权限操作的相关命令

文章目录问题:前言:用户和用户组概念前言一、用户前言二、用户组一、添加用户和用户组二、查看用户所属组命令、三、管理用户组方法一、gpasswd命令方式二、newgrp命令方式三、usermod命令用户组实战:赋予用户root权限四、文件修改权限命令ch…

数字孪生与 UWB 技术创新融合:从单点测量到全局智能化

人员定位是指利用各种定位技术对人员在特定场所的位置进行准确定位的技术。人员定位技术主要应用于需要实时监控、管理和保障人员安全的场所,如大型厂区、仓库、医院、学校、商场等。人员定位技术的应用范围非常广泛,例如:-在工厂生产线上&am…

服务器Nginx安装实战

因为Vue项目发布在Tomcat中出现跨域为,所以需要Nginx进行反向代理,所以特此在云服务器中安装Nginx,本文章记录安装过程及解决安装过程中的错误处理。 一、Nginx 安装 登录服务器后,执行命令 yum info gcc-c pcre pcre-devel zl…

keras lstm

keras lstm的参数(1)units:LSTM层的单元个数,即LSTM网络中隐藏节点的数量。(2)activation:激活函数,用于更新内部状态的函数(即门的决策函数)。(3…

dotConnect Universal 4.0.134 Crack

dotConnect Universal 能够呈现和访问不同于Microsoft 和框架的数据库的信息。网。它能够支持大多数数据库服务器以及 Microsoft Access、Oracle、MySQL、DB2、PostgreSQL、SQLite、InterBase、FireBird,最后是 Microsoft SQL Server。它可以通过 ODBC、OLE DB、ADO…

我来跟你讲vue进阶

一、组件(重点) 组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象…

ThreadLocal 的简单使用并深扒其实现原理

在多线程环境下, 如果想要保证每个线程都能独立于其它线程独自运行, 可以使用 ThreadLocal 来解决; ThreadLocal 就是用于提供线程局部变量的一个工具, 也就是说 ThreadLocal 可以为每个线程创建一个单独的变量副本; 其概念与同步机制正好相反, 同步机制是保证多线程环境下数据…

elasticSearch写入原理

elasticSearch写入原理 最近学习完了es相关的课程整理除了es的核心内容,学习这东西知其然知其所以然,自己按照自己的理解整理了es相关的面试题。先热个身,整理一下es的写入原理,有不对的地方请大家指正。 这些原理的东西我觉得还是…

MySql数据库(进阶篇)

👌 棒棒有言:人生总是在前行,不论走到哪里,只要带着信念往前走,比别人多一点努力,你就会多一份成绩;比别人多一点志气,你就会多一份出息;比别人多一点坚持,你…

js学习3(数组)

目录 结构图 数组操作 每日一练 结构图 数组操作 ## 数组中可以存储任何类型元素 ## 创建: 字面量([...])、创建对象(new Array(arr_len)) ## 遍历: 循环遍历、forEach(callback)、map(callback)、filter(callback)、every(callback)、some(callback)、…

1637_fgets函数的功能

全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 没想到分析一个函数的实现会这么麻烦,中间利用的一系列的库函数以及内核接口我全都不熟悉。但是,这次的这个函数应该是之前C语言的基本教程…

vscode下载与使用

1.vscode下载 官网下载地址:Download Visual Studio Code - Mac, Linux, Windows下载太慢,推荐文章:解决VsCode下载慢问题_vscode下载太慢_迷小圈的博客-CSDN博客下载太慢,推荐下载链接:https://vscode.cdn.azure.cn/s…

JavaScript Array(数组)对象

数组对象的作用是:使用单独的变量名来存储一系列的值。参数参数 size 是期望的数组元素个数。返回的数组,length 字段将被设为 size 的值。参数 element ...; elementn 是参数列表。当使用这些参数来调用构造函数 Array() 时,新创建的数组的元…

SEO技术风口来了|SEO能否抓住全球约93%的网络用户?

开篇词作者/出品人 | 美洽 SEO 流量专家 白桦为什么要做一个 SEO 专栏?在一部分人眼中,SEO(搜索引擎优化)已经是老掉牙的玩意儿,在这个信息爆炸的年代,它似乎已经无法承担吸引流量的主要作用。但&#xff…