1、uniapp加水印
1.1、创建画布容器
- <canvas class="watermark-canvas" id="watermark-canvas" canvas-id="watermark-canvas"
- :style="{ width: canvasWidth, height: canvasHeight }" />
1.2、获取水印内容
- famartWeek(e) {
- switch (e) {
- case 0:
- return '日'
- case 1:
- return '一'
- case 2:
- return '二'
- case 3:
- return '三'
- case 4:
- return '四'
- case 5:
- return '五'
- case 6:
- return '六'
- }
- },
- async getLocation() {
- const zero = (item) => item < 10 ? "0" + item : item
- const time = new Date();
- const yy = time.getFullYear();
- const mm = time.getMonth() + 1;
- const dd = time.getDate();
- const hh = time.getHours();
- const MM = time.getMinutes();
- const ww = this.famartWeek(time.getDay())
-
- const hm = zero(hh) + ':' + zero(MM)
- const ymd = yy + '-' + zero(mm) + '-' + zero(dd) + ' 星期' + ww
-
- const {
- name: location
- } = await this.$store.dispatch('location/juGetLocation')
-
- return {
- hm,
- ymd,
- address: location
- }
- },
1.3、添加水印上传图片
- async chooseImage(e) {
-
- uni.chooseImage({
- sourceType: sourceType[this.sourceTypeIndex],
- sizeType: ['compressed'],
- count: this.limit,
- success: async (res) => {
- let filePath = res.tempFilePaths[0]
- const watermark = await this.getLocation()
- //压缩图片设置宽度,不然画不全
- uni.compressImage({
- src: filePath,
- quality: 80,
- compressedHeight: 1200,
- success: async comres => {
- //绘制图片加水印
- let img = await this.fillTextToImg(comres.tempFilePath, watermark)
- uni.showLoading({
- title: '上传中...',
- mask: true
- })
- const arr = [img]
- // 上传图片
- const key = await this.$store.dispatch('upload/uploadFileList', arr)
- this.$emit('handleChangeKeys', {
- src: key,
- create_time: watermark.hm,
- sign_date: watermark.ymd,
- sign_local: watermark.address
- })
-
- uni.hideLoading()
- }
- })
-
- },
-
- fail: (err) => {}
- })
- },
- sleep(millisecond) {
- return new Promise((resolve) => {
- setTimeout(resolve, millisecond)
- })
- },
- fillTextToImg(file, watermark) {
- return new Promise((resolve, reject) => {
- uni.getImageInfo({
- src: file,
- success: async res => {
- //设置画布大小,然后再画,不然会只画一部分
- this.canvasWidth = `${res.width}px`
- this.canvasHeight = `${res.height}px`
- console.log(res.width, res.height);
- const bol = res.width < res.height
- let waterW = res.width
- if (bol && waterW < 650) {
- waterW = 650
- }
- if (bol && waterW > 800) {
- waterW = 800
- }
- if (!bol) {
- waterW = 800
- }
- await this.sleep(200)
- const ctx = uni.createCanvasContext('watermark-canvas', this)
- ctx.clearRect(0, 0, res.width, res.height)
- ctx.beginPath()
- ctx.drawImage(res.path, 0, 0, res.width, res.height)
-
- // 水印 字体大小,颜色,内容,位置
- ctx.beginPath()
- ctx.font = 'bold 24px 黑体'
- // 背景
- let fw = waterW / 12
- ctx.fillStyle = "rgb(24,177,237)";
- ctx.fillRect(10, res.height / 4 * 2.8, fw * 4.2, fw * 1.4);
-
- ctx.textBaseline = 'top'
- ctx.setFillStyle('#ffffff')
- ctx.setFontSize(fw)
- ctx.fillText('家宴打卡', 10, res.height / 4 * 2.8 + 10)
-
- // 背景
- ctx.fillStyle = "#ffffff";
- ctx.fillRect(10, res.height / 4 * 2.8 + fw * 1.4, fw * 4.2, fw * 1.4);
- ctx.setFillStyle('rgb(31,53,93)')
- ctx.setFontSize(waterW / 9)
- ctx.fillText(watermark.hm, 10, res.height / 4 * 2.8 + fw * 1.4)
-
- ctx.setFillStyle('#ffffff')
- ctx.setFontSize(waterW / 14)
- ctx.fillText(watermark.ymd, 10, res.height / 4 * 2.8 + fw * 1.4 * 2.2)
-
- ctx.setFontSize(waterW / 16)
- ctx.fillText(watermark.address, 10, res.height / 4 * 2.8 + fw * 1.4 * 3)
- // 开始绘制 (canvas -> 临时文件路径)
- ctx.draw(false, async () => {
- await this.sleep(500) // 某些平台 canvas 渲染慢,需要等待
-
- uni.canvasToTempFilePath({
- canvasId: 'watermark-canvas',
- destWidth: res.width,
- destHeight: res.height,
- fileType: 'jpg',
- quality: 0.8,
- success: (fileRes) => {
- resolve(fileRes.tempFilePath)
- },
- fail: (err) => {
- uni.showToast({
- title: err.errMsg,
- icon: 'none'
- })
- reject()
- },
- },
- this,
- )
- })
- },
- fail: (err) => {
- console.log('[Error getImageInfo]', err)
- uni.showToast({
- title: err.errMsg,
- icon: 'none'
- })
- reject()
- },
- })
- });
- },
1.4、设置画布位置,不让其显示
- .watermark-canvas {
- transform: scale(1);
- transform-origin: 0 0;
- position: absolute;
- top: -999px;
- left: -999px;
- }
ps:效果图

2、web端加水印(Image,FileReaderweb端才能使用)
- // 获取本地图片的base64编码
- // 使用在线图片链接的时候需要注意给图片设置crossOrigin属性
- function fileToBase64Async(file) {
- return new Promise((resolve, reject) => {
- let reader = new FileReader();
- reader.readAsDataURL(file);
- reader.onload = (e) => {
- resolve(e.target.result);
- };
- });
- }
-
- // fillText绘制的是默认的普通实线文本,strokeText绘制的是描边文本
- function fillTextToImg(base64) {
- const img = new Image();
- img.src = base64;
- img.setAttribute("crossOrigin", "Anonymous");
- return new Promise((resolve, reject) => {
- img.onload = () => {
- // 生成一个 canvas 画布;
- const canvas = document.createElement("canvas");
- canvas.width = img.width;
- canvas.height = img.height;
- // 将现有需要添加水印的图片绘制到画布上;
- const ctx = canvas.getContext("2d");
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
- const remFontSize = canvas.width / 35;
- ctx.font = "bolder " + remFontSize + "px Verdana";
- ctx.textAlign = "center";
- /**
- ctx.textAlign = "center|end|left|right|start";
- start:默认,文本在指定的位置开始。
- end:文本在指定的位置结束。
- center:文本的中心在指定的位置。
- left:文本左对齐。
- right:文本右对齐。
- **/
- ctx.strokeStyle = "#fff";
- const name = "@AAAAAAAAAAAAA";
- const spaceH = remFontSize * 0.3;
- ctx.fillText(
- name,
- canvas.width / 2,
- canvas.height - remFontSize - spaceH
- );
- resolve(canvas.toDataURL("image/jpeg"));
- };
- });
- }