vue之原生上传图片并压缩图片大小
vue之PC原生上传图片加水印
<template>
<div class="content-box">
<div class="container">
<div class="title">
点击上传图像(支持image/jpg,image/jpeg,image/png,image/gif格式图片且大小不能超过10MB)
</div>
<div class="uploadImg">
<span class="el-icon-plus"></span>
<input
:accept="accept"
type="file"
class="upload_ipu"
ref="fileLoad"
@change="uploadImg"
/>
</div>
<div class="imgList">
<img v-if="imgShow" :src="imgSrc"/>
</div>
<!-- 图片上传水印 -->
<div id="markImg">
<div class="logo">
<img src="@/assets/logo.png" />
图片水印
</div>
<p>
{{ parseTime(fileDate, '{y}-{m}-{d} {h}:{i}:{s}') }} 周{{
parseTime(fileDate, '{a}')
}}
</p>
<p>{{ loginName }}</p>
</div>
</div>
</div>
</template>
<script>
import { parseTime } from '@/utils'
import { compressor, addWaterMarker } from '@/utils/waterMarker'
export default {
props: {
accept: {
type: String,
default: 'image/jpg,image/jpeg,image/png,image/gif'
}
},
data() {
return {
imgShow: false,
imgSrc: '',
loginName: 'fqniu',
fileDate: new Date(),
needWaterMark: true
}
},
created() {
this.parseTime = parseTime
},
methods: {
createUrl(file) {
if (window.URL) {
return window.URL.createObjectURL(file)
} else if (window.webkitURL) {
return window.webkitURL.createObjectURL(file)
} else {
return null
}
},
async uploadImg() {
// 这个是元素dom节点
console.log(this.$refs.fileLoad);
// 上传文件fileList
console.log(this.$refs.fileLoad.files);
let file = this.$refs.fileLoad.files[0]
let size = file.size / 1024 / 1024
console.log(file, file.lastModifiedDate)
if (!this.accept.includes(file.type.toLowerCase())) {
this.$message.error('图片格式不正确!')
return false
}
if (size > 10) {
this.$message.error('图片大小不能超过10MB!')
return false
}
// 压缩图片
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', 'leftDown')
file.name = fileName
}
this.imgSrc = this.createUrl(file)
this.imgShow = true
this.$message.success('上传成功!')
}
}
}
</script>
<style lang="scss" scoped>
.title {
font-size: 16px;
color: #aaa;
}
.uploadImg {
margin-top: 20px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 180px;
height: 180px;
transition: all 0.2s;
&:hover {
border-color: #409eff;
}
span {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.upload_ipu {
opacity: 0;
width: 100%;
height: 100%;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
z-index: 2;
}
img {
width: 178px;
height: 178px;
position: absolute;
border-radius: 6px;
left: 0;
top: 0;
z-index: 1;
}
}
.imgList {
width: 550px;
height: 400px;
img {
width: 100%;
height: 100%;
}
}
// 水印样式
#markImg {
position: absolute;
left: -9999999px;
text-align: left;
padding: 10px 15px;
.logo {
font-weight: 600;
font-size: 15px;
color: #ffffff;
display: flex;
height: 21px;
align-items: center;
justify-content: flex-start;
img {
height: 21px;
margin-right: 5px;
}
}
p {
margin-top: 6px;
color: #ffffff;
font-size: 12px;
font-weight: 400;
}
}
</style>
封装水印方法如下
感谢龙哥帮忙指导
import Compressor from 'compressorjs'
import html2canvas from 'html2canvas'
/**
* 压缩和旋转图片
* @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 = '#markImg', 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)
}
})
}
以上代码可以直接使用