Vue图片上传压缩(放大左右滑动)
描述: 早在17年入行的时候就有需求做图片上传,其实很简单几个步骤就可以搞定
- 备注: 样式采用计算px转rem
- 主要效果
主要步骤
文件上传
图片压缩
放大滑动
- 涉及input,canvas,swiper
dom
<template>
<!--轮播-->
<div class="upload">
<div class="upload_img">
<div class="img_list" v-for="(item, index) in imgList" :key="index" @click="scaleLargeSwiper(index)">
<img class="img_close" src="../../../assets/image/common/close.png" @click="delImg(index, $event)">
<img class="img" :src="item">
</div>
<div class="img_list upload_line" v-if="imgList.length < maxImgLength">
<span>+</span>
<input ref="input" type="file" name="file" accept="image/*" multiple="multiple" @input="handleFileChange">
</div>
</div>
<!--轮播-->
<swiper v-if="isShowSwiper"
@closeModel="closeModel"
:imgList="imgList"
:defaultIndex="defaultIndex"></swiper>
</div>
</template>
js
<script>
import swiper from "./swiper";
export default {
name: "upload",
components: {swiper},
props: {
// 按钮文字
btnTitle: {
default: '',
type: String
},
// 最大图片数
maxImgLength: {
default: 5,
type: Number
},
// 默认已有图片
outImgList: {
type: Array,
default() {
return []
}
},
// 最大上传
maxSize: {
default: 2,
type: Number
},
text: {
default: ''
}
},
data(){
return {
// 图片最大宽度
maxWidth: 1000,
// 图片最大高度
maxHeight: 1000,
// 图片集合
imgList: [],
// 是否显示轮播
isShowSwiper: false,
// 默认显示索引
defaultIndex: 0,
// 显示loading
isLoading: false
}
},
created() {
this.imgList = [...this.outImgList]
},
methods: {
// 选择图片处理
handleFileChange() {
let files = this.$refs.input.files
let size,
len = files.length > this.maxImgLength ? this.maxImgLength : files.length
for (let i = 0; i < len; i++) {
size = files[i].size / 1024 / 1024
let FR = new FileReader()
FR.readAsDataURL(files[i]);
FR.onload = (e) => {
// 大于2M
if (Math.floor(size) > 2) {
this.checkImgSize(e.target.result)
} else {
this.imgList.push(e.target.result)
this.$emit('addImg', this.imgList)
}
}
}
},
// 校验图片大小
checkImgSize(url) {
let img = new Image()
img.src = url
img.onload = () => {
let { width: originW, height: originH } = img
if (originW > this.maxWidth || originH > this.maxHeight) {
if (originW > originH) {
//宽大于高
let rat = Math.ceil(originW / this.maxWidth),
targetW = Math.floor(originW / rat), //目标的宽度
targetH = Math.floor(originH / rat) //目标的高度
this.imgPress(img, targetW, targetH )
} else {
//高大于宽
Let rat = Math.ceil(originH / this.maxHeight),
targetW= Math.floor(originW / rat),
targetH = Math.floor(originH / rat)
this.imgPress( img, targetW, targetH )
}
}
}
},
// 图片压缩
imgPress(img, w, h) {
let canvas = document.createElement('canvas’),
ctx = canvas.getContext('2d’),
anw = document.createAttribute('width’),
anh = document.createAttribute('height')
anw.nodeValue = w
anh.nodeValue = h
canvas.setAttributeNode(anw)
canvas.setAttributeNode(anh)
ctx.drawImage(img, 0, 0, w, h)
let base64 = canvas.toDataURL('image/jpeg', 0.9)
this.imgList.push(base64)
this.$emit('addImg', this.imgList)
},
// 删除图片
delImg(index, e) {
e.stopPropagation()
this.imgList.splice(index, 1)
this.$refs.input && (this.$refs.input.value = null)
this.$emit('delImg', this.imgList)
},
// 放大轮播
scaleLargeSwiper(id) {
this.isShowSwiper = true
this.defaultIndex = id
},
// 关闭model
closeModel(bool) {
this.isShowSwiper = bool
}
}
}
</script>
> less
<style scoped lang="less">
// 上传及描述
.upload {
// 上传图片
.upload_img {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.img_list {
margin-top: 24px;
width: 160px;
height: 160px;
overflow: hidden;
margin-right: 20px;
position: relative;
.img_close {
position: absolute;
top: 0;
right: 0;
width: 34px;
height: 34px;
}
.img {
width: 160px;
height: 160px;
border-radius: 8px;
display: block;
}
}
.img_list:nth-child(3n) {
margin-right: 0;
}
}
.upload_line {
border: 1px dashed #CCCCCC;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
input {
width: 160px;
height: 160px;
position: absolute;
opacity: 0;
}
span{
color: #969798;
font-size: 100px;
}
}
}
</style>
引用
<template>
<section>
<upload @addImg="addImg" @delImg="delImg"></upload>
</section>
</template>
<script>
import upload from './common/upload'
export default {
components: {upload},
data(){
return {
imgList: []
}
},
methods: {
// 删除图片
delImg(imgList){
this.imgList = imgList
},
// 新增图片
addImg(imgList){
this.imgList = imgList
}
}
}
</script>
整体来说还是比较容易实现简单的图片上传,此外你还可以做其他操作,比如放大之后的缩放,上传之后base64转Blob等