vue实现上传图片添加水印(升级版)
vue项目实现上传图片添加水印升级版,供大家参考,具体内容如下
封装水印方法
/**
* 添加水印
* @param {blob} file
* @param {string} el
* @returns {Promise}
*/
export async function addWaterMarker(file, el = '#markImg') {
return new Promise(async (resolve, reject) => {
try {
// 先压缩和旋转图片
file = await compressor(file)
// 将文件blob转换成图片
let img = await blobToImg(file)
// 创建canvas画布
let canvas = document.createElement('canvas')
canvas.width = img.naturalWidth
canvas.height = img.naturalHeight
let ctx = canvas.getContext('2d')
// 填充上传的图片
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
// 生成水印图片
const markEle = document.querySelector(el)
const markWidth = markEle.clientWidth
const scale = canvas.width * 0.25 / markWidth
// 先缩放水印再转成图片
markEle.style.transform = `scale(${scale})`
const markImg = await htmlToCanvas(markEle)
// 填充水印
ctx.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
// 将canvas转换成blob
canvas.toBlob(blob => resolve(blob))
} catch (error) {
reject(error)
}
})
}
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)
})
}
export function htmlToCanvas(el, backgroundColor = 'rgba(0,0,0,.1)') {
return new Promise(async (resolve, reject) => {
try {
const markImg = await html2canvas(el, {
scale: 2, //此处不使用默认值window.devicePixelRatio,需跟移动端保持一致
allowTaint: false, //允许污染
useCORS: true,
backgroundColor //'transparent' //背景色
})
resolve(markImg)
} catch (error) {
reject(error)
}
})
}
/**
* 压缩和旋转图片
* @param {blob} file
* @param {number} quality 压缩比例
* @param {number} maxWidth
* @returns {Promise}
*/
export function compressor(file, quality = 0.6, maxWidth = 750) {
return new Promise(resolve => {
new Compressor(file, {
maxWidth,
quality,
success: resolve,
error(err) {
console.log(err.message)
}
})
})
}
页面中使用水印并压缩图片
<template>
<div>
<el-upload
action=""
:headers="uploadProps.headers"
list-type="picture-card"
:show-file-list="false"
:http-request="fnUploadRequest"
:on-success="handleSuccess"
:before-upload="handleUpload"
accept=".png,.jpg,.jpeg,.gif,.webp"
>
<div class="flex-center">
<slot></slot>
</div>
</el-upload>
<!-- 图片上传水印 -->
<div id="markImg">
<div class="logo">
<img src="@/assets/img/icon-logo.png" />
文本文本
</div>
<p>
{{ parseTime(fileDate, '{y}-{m}-{d} {h}:{i}:{s}') }} 周{{
parseTime(fileDate, '{a}')
}}
</p>
<p>{{ executor }}</p>
</div>
</div>
</template>
<script>
import {
getAccessToken,
getRefreshToken,
getAccessTokenTTL
} from '@/utils/auth'
import { uploadOSS } from '@/utils/ossImage'
import { parseTime, compressor, addWaterMarker } from '@/utils'
export default {
name: 'index',
props: {
needWaterMark: {
type: Boolean,
default: false
},
executor: {
type: String,
default: ''
}
},
data() {
return {
fileDate: new Date()
}
},
created() {
this.parseTime = parseTime
},
computed: {
userAccountID() {
return this.$store.state.user.userAccountID
},
uploadProps() {
return {
// action: `${process.env.VUE_APP_BASE_API}/api/image/upload`,
headers: {
// 接口可能要带token: "",
Authorization: getAccessToken()
},
data: {}
}
}
},
methods: {
// beforeUpload_u(file, fileList){
// // console.log(file, fileList);
// var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
// const extension = testmsg === 'png' || testmsg === 'jpg' || testmsg === 'jpeg' || testmsg === 'gif' || testmsg === 'webp'
// const isLimit10M = file.size / 1024 / 1024 < 10
// var bool = false;
// if(extension && isLimit10M){
// bool = true;
// } else {
// bool = false;
// }
// if(!extension) {
// this.$message.error('请上传图片格式文件!');
// return bool;
// }
// if(!isLimit10M) {
// this.$message.error('上传失败,不能超过10M!');
// return bool;
// }
// return bool;
// },
// handleSuccess(res) {
// console.log(res);
// if (res.code == 0) {
// this.$emit('imgData', res.item);
// this.$message.success('上传图片成功!');
// } else {
// this.$message.error('上传图片失败!');
// }
// },
// handleError(err){
// this.$message.error('上传图片失败!');
// },
// 上传图片判断
handleUpload(file, fileList) {
var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
const extension =
testmsg.toLowerCase() === 'png' ||
testmsg.toLowerCase() === 'jpg' ||
testmsg.toLowerCase() === 'jpeg' ||
testmsg.toLowerCase() === 'gif' ||
testmsg.toLowerCase() === 'webp'
const isLimit10M = file.size / 1024 / 1024 < 10
var bool = false
if (extension && isLimit10M) {
bool = true
} else {
bool = false
}
if (!extension) {
this.$message.error('请上传图片格式文件!')
return bool
}
if (!isLimit10M) {
this.$message.error('上传失败,不能超过10M!')
return bool
}
return bool
},
// 上传图片
async fnUploadRequest(options) {
try {
let file = options.file // 拿到 file
this.fileDate = file.lastModifiedDate
// 压缩图片
if (file.size > 512 * 1024 && file.type.includes('image/')) {
file = await compressor(file)
}
// 添加水印
if (this.needWaterMark) {
const fileName = file.name
file = await addWaterMarker(file, '#markImg')
file.name = fileName
}
let res = await uploadOSS(file)
// 返回的就是图片地址
this.$emit('imgData', res)
this.$message.success('上传图片成功!')
} catch (e) {
console.log(e)
this.$message.error('上传图片失败!请重新上传')
}
},
//图片上传成功回调
handleSuccess(res) {
// console.log(res);
if (res) {
this.$emit('imgData', res)
}
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-upload,
::v-deep .el-upload--picture-card {
// width: 120px;
height: 24px;
height: 0;
border: none;
line-height: 0;
display: block;
background: #f5f6fb;
}
// ::v-deep .el-upload{
// width: 50px;
// }
.img-cont {
width: 50px;
height: 24px;
background: #f5f6fb;
.img-icon {
color: #ccc;
}
.img-text {
font-size: 12px;
height: 24px;
color: #000;
}
}
#markImg {
position: absolute;
left: -9999999px;
text-align: right;
padding: 10px 15px;
.logo {
font-weight: 600;
font-size: 15px;
color: #ffffff;
display: flex;
height: 21px;
align-items: center;
justify-content: flex-end;
img {
height: 21px;
margin-right: 5px;
}
}
p {
margin-top: 6px;
color: #ffffff;
font-size: 12px;
font-weight: 400;
}
}
</style>
水印方法更新版
/**
* 压缩和旋转图片
* @param {blob} file
* @param {number} quality 压缩比例
* @param {number} maxWidth
* @returns {Promise}
*/
export function compressor(file, drew, maxWidth = 750, quality = 0.6) {
return new Promise(resolve => {
new Compressor(file, {
strict: false,
maxWidth,
quality,
drew,
success: resolve,
error(err) {
console.log(err.message)
}
})
})
}
/**
* 添加水印
* @param {blob} file
* @param {string} el
* @returns {Promise}
*/
export async function addWaterMarker(file, el = '#brandMarkImg', direction = 'rightDown') {
return new Promise(async (resolve, reject) => {
try {
const maxWidth = 750
const img = await blobToImg(file)
const imgWidth = img.naturalWidth > maxWidth ? maxWidth : img.naturalWidth
// 生成水印图片
const markEle = document.querySelector(el)
const scale = imgWidth * 0.25 / markEle.clientWidth
// 先缩放水印再转成图片
markEle.style.transform = `scale(${scale})`
const markImg = await htmlToCanvas(markEle)
// 先压缩和旋转图片
file = await compressor(file, (context, canvas) => {
if(direction == 'rightDown'){
// 填充水印 右下角
context.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
} else {
// 填充水印 左下角
context.drawImage(markImg, 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
}
}, maxWidth)
resolve(file)
} catch (error) {
reject(error)
}
})
}
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)
})
}
export function htmlToCanvas(el, backgroundColor = 'rgba(0,0,0,.1)') {
return new Promise(async (resolve, reject) => {
try {
const markImg = await html2canvas(el, {
scale: 2,
allowTaint: false, //允许污染
useCORS: true,
backgroundColor //'transparent' //背景色
})
resolve(markImg)
} catch (error) {
reject(error)
}
})
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
以上是 vue实现上传图片添加水印(升级版) 的全部内容, 来源链接: utcz.com/p/239702.html