实现效果:可添加logo.(注:这里主要实现添加水印.图片上传用的vant的上传)
大致思路:
将上传的file文件转成base64(代码如下)
const reader = new FileReader();
reader.readAsDataURL(file);//file转base64
再将图片用canvas绘制添加文字logo:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (ctx == null) return
const img = new Image();
if (e.target == null) return
img.src = e.target.result as string;
img.onload = () => {
let imgWidth = img.width;
let imgHeight = img.height;
canvas.width = imgWidth;//画布宽度
canvas.height = imgHeight;//画布高度
let imgurl = ""
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致
/**
这基础上在进行添加水印
具体看全代码
*/
.....
}
<template>
<div>
<van-uploader :after-read="afterRead" />
<!-- 图片回显 -->
<img :src="data.imgurl" alt="">
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { showToast } from 'vant';
import { onMounted, defineProps } from 'vue';
const props = defineProps({
//logo图
logoUrl: {
type: String,
default: require('@/assets/panda.png'),
required: false
},
options: {
type: Object,
default() {
return {
imgurlTop: 0
}
},
required: false
},
title: {
type: String,// 如果可能存在多个类型,则可以写成 [String,Number]
default: '限定制作',
required: false// 是否必传 ,在不声明为true 的情况下,所有prop 默认为非必填。
}
})
let data = reactive({
imgurl: "",
newimg: props.logoUrl
});
onMounted(() => {
console.log("_++++_", props.title, props.options)
})
const afterRead = (file: any) => {
// 此时可以自行将文件上传至服务器
showToast('上传成功!');
// data.imgurl = file.content;
watermark(file.file).then(res => {
data.imgurl = res as string
})
};
const getBase64Image = (src: string) => {
return new Promise(resolve => {
const img = new Image()
img.crossOrigin = ''
console.log(src)
img.src = src
img.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx?.drawImage(img, 0, 0, img.width, img.height)
const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase()
const dataURL = canvas.toDataURL('image/' + ext)
resolve(dataURL)
}
})
}
const watermark = (file: any) => {
return new Promise(resolve => {
const reader = new FileReader();
reader.readAsDataURL(file);//file转base64
reader.onload = (e) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (ctx == null) return
const img = new Image();
if (e.target == null) return
img.src = e.target.result as string;
img.onload = () => {
let imgWidth = img.width;
let imgHeight = img.height;
// let fontsize = imgWidth > imgHeight ? imgHeight / 20 : imgWidth / 20;//设定文字大小随图片大小变化
canvas.width = imgWidth;//画布宽度
canvas.height = imgHeight;//画布高度
let imgurl = ""
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致
/**
* 再添加logo图片
* as string 是 TypeScript 中的语法,用于将 data.newimg 强制转换为字符串类型。它告诉编译器将变量视为指定的类型,以便进行类型检查和代码补全等操作。
*
* smallImg.setAttribute('crossOrigin', 'anonymous')解决图片跨域
*/
const smallImg = new Image();
getBase64Image(data.newimg as string).then(res => {
smallImg.src = res as string
})
// //
smallImg.onload = () => {
console.log(smallImg.width, smallImg.height)
ctx.shadowOffsetX = 0;//用来设定阴影在 X轴的延伸距
ctx.shadowOffsetY = 0;//用来设定阴影在 Y轴的延伸距
//设置logo的位置
ctx.drawImage(smallImg, imgWidth - smallImg.width / 7, imgHeight - smallImg.height / 7, smallImg.width / 7, smallImg.height / 7);
let fontsize = smallImg.width > smallImg.height ? smallImg.height / 20 : smallImg.width / 20;//设定文字大小随图片大小变化
ctx.textBaseline = 'bottom';//水印对其的基准线
ctx.font = `${fontsize}px Verdana`;//文字大小
ctx.shadowOffsetX = -1;//用来设定阴影在 X轴的延伸距
ctx.shadowOffsetY = -1;//用来设定阴影在 Y轴的延伸距
ctx.shadowBlur = 0;//设定阴影的模糊程度 默认0
ctx.shadowColor = "rgba(0, 0, 0, 0.95)";//设定阴影颜色效果
ctx.fillStyle = "#fff";//设置字体颜色
//修改文字的位置
ctx.fillText(props.title, imgWidth - ctx.measureText(props.title).width - smallImg.width / 7 - 10, imgHeight - 20);
imgurl = canvas.toDataURL(file.type); //输出压缩后的base64
resolve(imgurl)
}
}
}
})
}
</script>
<style lang="less" scoped></style>