El-Upload组件上传图片并添加水印
背景
有的时候我们需要在上传图片中添加一些水印标识,然后上传至服务器
效果图
代码
需求:
-
- 点击直接预览图片,而不需要使用dialog
-
- 上传图片添加水印后才预览图片
- 上传图片文件添加水印。使用watermarkjs库转换
- 将添加水印的图片转换成base64,更新预览图片的内容,否则预览的图片还是旧的
- 保存添加水印后的文件
- 自行上传服务器....
<template>
<div class="app">
<el-upload
action=""
list-type="picture-card"
:multiple="true"
:on-change="handleUploadChange"
:auto-upload="false"
>
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{ file }">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in"></i>
<!-- <el-image
style="width: 100px; height: 100px"
:src="dialogImageUrl"
:preview-src-list="[dialogImageUrl]"
>
</el-image> -->
</span>
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
<!--
预览图片方式1:使用dialog方式
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog> -->
<!-- 预览图片方式2:使用image-viewer -->
<el-image-viewer
v-if="imgViewerVisible"
:url-list="imgList"
:on-close="closeImgViewer"
/>
<div class="demo" ref="demoRef"></div>
</div>
</template>
<script>
import watermark from 'watermarkjs'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
export default {
components: {
ElImageViewer,
},
data() {
return {
dialogImageUrl: '',
dialogVisible: false,
imgViewerVisible: false,
imgList: [],
}
},
methods: {
handlePictureCardPreview(file) {
// this.dialogImageUrl = file.url
// this.dialogVisible = true
this.imgViewerVisible = true
this.imgList = [file.url]
// 解决预览放大后滚动鼠标页面跟着滚动的问题
const m = (e) => {
e.preventDefault()
}
document.body.style.overflow = 'hidden'
document.addEventListener('touchmove', m, false) // 禁止页面滑动
},
closeImgViewer() {
this.imgViewerVisible = false
const m = (e) => {
e.preventDefault()
}
document.body.style.overflow = 'auto'
document.removeEventListener('touchmove', m, true)
},
handleRemove(file) {
console.log(file)
},
handleUploadChange(file, fileList) {
// console.log('file:', file)
// console.log('fileList:', fileList)
const upload_file = file.raw
// 1. 添加单个水印
// watermark([upload_file])
// .image(
// watermark.text.upperRight(
// 'watermark.js',
// '48px Josefin Slab',
// '#fff',
// 0.5,
// 48
// )
// )
// .then((img) => {
// img.style.width = '300px'
// img.style.height = 'auto'
// this.$refs.demoRef.append(img)
// })
// 2. 添加多个水印
// watermark([upload_file])
// .image(
// watermark.text.upperRight(
// '呵呵呵',
// '48px Josefin Slab',
// '#fff',
// 0.5,
// 48
// )
// )
// .render()
// .image(
// watermark.text.upperLeft(
// '哈哈哈',
// '48px Josefin Slab',
// '#fff',
// 0.5,
// 48
// )
// )
// .then((img) => {
// img.style.width = '300px'
// img.style.height = 'auto'
// this.$refs.demoRef.append(img)
// })
// 3. 自定义添加水印位置,比如:设置在右上角
// @param {HTMLCanvasElement} canvas
// @param {TextMetrics} metrics
// @param {CanvasRenderingContex2D} context - context of the canvas
// 设置水印的x坐标
// var x = function (canvas, metrics, context) {
// // 微调,比如:-20 根据实际调整
// return canvas.width - metrics.width - 20
// }
// // 设置水印的y坐标
// var y = function (canvas, metrics, context) {
// return metrics.hangingBaseline + 10
// }
// watermark([upload_file])
// .image(
// watermark.text.atPos(
// x,
// y,
// '上传时间:2024-05-08 22:40:10',
// '48px sans-serif',
// '#f00',
// 0.8
// )
// )
// .then((img) => {
// this.$refs.demoRef.append(img)
// // 将base64转文件形式
// const watermark_file = this.dataURLtoFile(img.src, file.name)
// // 下载文件
// // this.downloadFile(watermark_file)
// this.transformFileToBase64(watermark_file, file)
// })
// 根据图片大小自适应设置水印文字大小
function customFn(target) {
var context = target.getContext('2d')
var text = 'watermark.js'
var metrics = context.measureText(text)
// var x = target.width / 2 - (metrics.width + 24)
// var y = target.height / 2 + 48 * 2
var x = 0.01 * target.width
var y = 0.04 * target.height
const fontSize = 0.05 * target.width
context.translate(x, y)
context.globalAlpha = 0.5
context.fillStyle = '#f00'
context.font = `700 ${fontSize}px Josefin Slab`
// context.rotate((-45 * Math.PI) / 180)
context.fillText(text, 0, 0)
return target
}
watermark([upload_file])
.image(customFn)
.then((img) => {
this.$refs.demoRef.append(img)
const watermark_file = this.dataURLtoFile(img.src, file.name)
this.transformFileToBase64(watermark_file, file)
})
},
// 将base64转文件
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
// 下载文件
downloadFile(file) {
let aTag = document.createElement('a') //创建一个a标签
aTag.download = file.name
let href = URL.createObjectURL(file) //获取url
aTag.href = href
aTag.click()
URL.revokeObjectURL(href) //释放url
},
// 将水印文件转换成base64,然后修改原有file对象的url,这样保证预览时图片的url是带有水印的
transformFileToBase64(watermark_file, file) {
return new Promise((resolve, reject) => {
// 读取文件
const reader = new FileReader()
//readAsDataURL()方法: 读取文件内容,结果用data:url的字符串形式表示
reader.readAsDataURL(watermark_file)
// 读取成功回调
reader.onload = () => {
file.url = reader.result
}
})
},
},
}
</script>
<style lang="less" scoped></style>
第三方库watermarkjs
链接:https://brianium.github.io/watermarkjs/docs.html#image
参考文档
- FileReader()读取文件、图片上传预览
https://www.cnblogs.com/libo-web/p/15766987.html - Element-ui中 使用图片查看器(el-image-viewer) 预览图片
https://juejin.cn/post/7084856145277354020