ps:从后台获取到图片数组,前端给每个图片添加水印;用canvas绘制,我是在网上找了篇文章,原文是单个图片点击放大才是水印图片,我是需要拿到水印图片渲染出来,再因为我的工程是vue3所以稍微改动了一下;原文参考链接:blog.csdn.net/strongbuger…
最终效果
1. 页面html代码
循环数组图片,以及没有水印的时候,添加图片加载钟提示语;
<div v-for="(item,index) in list" :key="index" class="phoneOnce">
<div class="imgDiv">
<img :src="item.pic" class="imgMain" v-if="item.showImg"/>
<span v-else> 图片正在加载中...</span>
</div>
<div class="phoneName">
{{item.name}}
</div>
</div>
复制代码
2. js代码
*因为是用canvas绘制图片,所以拿到的图片是需要有读写功能的;需要把权限放开
1.getBase64Image方法,先把图片链接变成base64
2.run方法,就是把图片和文字放入到canvas中,并调用方法得到法把水印的图片赋值到list中;
3.imgToCanvas图片绘制到canvas中;
4.addWatermark绘制水印文字;
<script setup>
import {ref,reactive,onMounted} from 'vue'
const text = ref('我是水印');//可以根据需要更改不同的文字
const list = reactive([
{
'pic':'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
'name':'web-vivi'
},
{
'pic':'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
'name':'web-vivi'
}
])
//onMounted
onMounted(()=>{
setTimeout(()=>{ //这里用setTimeout来模仿后台接口调用;
list.map((item,index)=>{
item.showImg = false;//图片赋值默认提示
getBase64Image(item.pic,index); //传入一个下标,下次赋值的时候才能找到这个下标
return item;
})
},1000)
});
const getBase64Image = ((imgUrl,index)=>{
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open("get", imgUrl, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status == 200) {
var blob = this.response;
let oFileReader = new FileReader();
oFileReader.onloadend = function (e) {
// 此处拿到的已经是 base64的图片了
let base64 = e.target.result;
run(base64,index)
};
oFileReader.readAsDataURL(blob);
}
}
xhr.send();
})
const run = async (imgUrl,index)=>{
// 1.图片路径转成canvas
const tempCanvas = await imgToCanvas(imgUrl);
// 2.canvas添加水印
const markText = text.value
const canvas = addWatermark(tempCanvas, markText);
// 3.canvas转成img
const img = convasToImg(canvas);
list[index].pic = img.src; // 把已经变成base64的图片赋值到数组中;
}
// 添加水印
const imgToCanvas= async (url)=> {
// 创建img元素
const img = document.createElement("img");
img.src = url;
img.setAttribute("crossOrigin", "anonymous"); // 防止跨域
await new Promise((resolve) => (img.onload = resolve));
// 创建canvas DOM元素,并设置其宽高和图片一样
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// 坐标(0,0) 表示从此处开始绘制,相当于偏移。
canvas.getContext("2d").drawImage(img, 0, 0);
return canvas;
}
/**
* canvas添加水印
* @param {canvas对象} canvas
* @param {水印文字} text
*/
const addWatermark = (canvas, text)=>{
const ctx = canvas.getContext("2d");
ctx.rotate(50 * Math.PI / 180) // 水印旋转角度
ctx.font = '30px Vedana'
ctx.fillStyle = '#000'
ctx.textAlign = 'center'
ctx.textBaseline = 'Middle'
let forIndex = canvas.width / 100 | 0
for(let i = -10; i < 10; i++) {
for(let j = -10; j < forIndex; j++) { //绘制多个文字
ctx.fillText(text, 300 * j, 150 * i + 75)
}
}
return canvas;
}
/**
* canvas转成img
* @param {canvas对象} canvas
*/
const convasToImg=(canvas=> {
// 新建Image对象,可以理解为DOM
var image = new Image();
// canvas.toDataURL 返回的是一串Base64编码的URL
// 指定格式 PNG
image.src = canvas.toDataURL("image/png");
return image;
});
</script>
复制代码