工作中遇到的需求 和大家分享下
- 以下代码完成图片上传
- 实线点击预览和删除图片
效果图
该组件上传图片的大致思路
1.利用H5的FileReader对象将上传的图片转成base64格式
2.利用canvas的drawImage方法重绘上传的图片
3.在利用canvas的toDataURL方法将图片压缩
4.将base64文件传递给后台(此项根据自己的项目需求来抉择,我的项目需求就是base64,所以我没有转成blob对象)
文件上传代码
1.使用input标签来获取图片文件
<form ref="uploadForm" id="uploadForm" style="display:inline;">
<input
type="file"
id="fileId"
ref="addPicFile"
name="file"
accept="image/jpg,image/jpeg,image/png,image/bmp"
style="display:none;"
@change="addPic"
/>
</form>
2.因为原生的按钮不满足我们需求,所以我们需要手动来做一个添加按钮
<!-- 项目需求最多不能超过5个图片,所以如果图片有5个我会自动隐藏按钮 -->
<img
class="addimg-items addBtn"
v-show="photoList.length < 5"
src="@/assets/img/添加图片.png"
@click="$refs.addPicFile.click()"
/>
3.上传图片js
//添加图片
addPic() {
// common的upload和compress方法是我自己写得js 我会在下面贴出代码
let file = common.upload(this.$refs.addPicFile);
let reader = new FileReader();
reader.onload = e => {
let img = new Image();
img.src = e.target.result;
img.onload = () => {
let imgsrc = common.compress(img);
this.$options.methods.uploadPic.bind(this)(imgsrc);
// 添加完成之后降input的值清空,如果不清空则会出现无法上传同一个图片的bug
this.$refs.addPicFile.value = "";
};
};
reader.readAsDataURL(file);
},
uploadPic(data) {
// HTTP是我自己封装的axios的调用代码
let res = Http.getAxios("POST", `/image/upload`, data);
res.then(data => {
// 因为我需要鼠标悬浮图片显示预览和删除按钮, 所以需要imgHover参数
this.list.push({
src: data.message,
imgHover: false
});
this.$emit("addPic", this.list);
});
}
4.common.js
//图片压缩
compress(img) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var width = img.width;
var height = img.height;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
var type = "image/jpeg";
var img64 = canvas.toDataURL(type, 0.3);
return img64;
}
//图片上传
upload(img) {
//判断是否支持FileReader
if (!window.FileReader) {
this.$Modal.warning({
title: "警告",
content: "您的设备不支持图片预览功能,如需该功能请升级您的设备!"
});
return;
}
var file = img.files[0];
//是否是图片
var imageType = /^image\//;
if (!imageType.test(file.type)) {
this.$Modal.warning({
title: "警告",
content: "请选择图片!"
});
return;
}
return file;
}
5.鼠标悬浮显示预览和删除按钮
<div class="showImg" v-for="(item, index) in photoList" :key="item.src">
<img
class="addimg-items"
v-show="photoList.length > 0"
:src="item.src"
@mouseenter="enter(item)"
@mouseleave="leave(item)"
/>
<div
class="demo-upload-list-cover"
v-show="item.imgHover"
@mouseenter="enter(item)"
@mouseleave="leave(item)"
>
<Icon type="ios-eye" @click="showImg(item.src)" />
<Icon type="ios-trash" @click="reset(index)" />
</div>
</div>
6.预览和删除JS操作
//移入
enter(item) {
item.imgHover = true;
},
//移出
leave(item) {
item.imgHover = false;
},
//查看大图
showImg(src) {
this.visible = true;
this.show.photo = src;
},
reset(index) {
this.list.splice(index, 1);
this.$emit("resetPic", this.list);
}
7.图片预览,我使用了iView的对话框Modal来预览图片
<Modal title="图片详情" v-model="visible">
<img :src="show.photo" v-if="visible" style="width: 100%" />
<div slot="footer"></div>
</Modal>
最后附上全部代码
<style lang="less" scoped>
.showImg {
position: relative;
float: left;
margin-right: 10px;
.demo-upload-list-cover {
width: 100px;
height: 100px;
padding: 33px 20px;
i {
font-size: 30px;
}
}
}
.addBtn {
float: left;
margin-right: 10px;
}
</style>
<template>
<div>
<form ref="uploadForm" id="uploadForm" style="display:inline;">
<input
type="file"
id="fileId"
ref="addPicFile"
name="file"
accept="image/jpg,image/jpeg,image/png,image/bmp"
style="display:none;"
@change="addPic"
/>
</form>
<div class="showImg" v-for="(item, index) in photoList" :key="item.src">
<img
class="addimg-items"
v-show="photoList.length > 0"
:src="item.src"
@mouseenter="enter(item)"
@mouseleave="leave(item)"
/>
<div
class="demo-upload-list-cover"
v-show="item.imgHover"
@mouseenter="enter(item)"
@mouseleave="leave(item)"
>
<Icon type="ios-eye" @click="showImg(item.src)" />
<Icon type="ios-trash" @click="reset(index)" />
</div>
</div>
<img
class="addimg-items addBtn"
v-show="photoList.length < 5"
src="@/assets/img/添加图片.png"
@click="$refs.addPicFile.click()"
/>
<Modal title="图片详情" v-model="visible">
<img :src="show.photo" v-if="visible" style="width: 100%" />
<div slot="footer"></div>
</Modal>
</div>
</template>
<script>
import common from "@/assets/js/common";
import Http from "@/utils/Network/Http";
export default {
components: {},
props: ["photo"],
data() {
return {
visible: false,
show: {
photo: ""
},
photoList: [],
list: []
};
},
computed: {},
watch: {},
methods: {
//移入
enter(item) {
item.imgHover = true;
},
//移出
leave(item) {
item.imgHover = false;
},
//查看大图
showImg(src) {
this.visible = true;
this.show.photo = src;
},
//添加图片
addPic() {
let file = common.upload(this.$refs.addPicFile);
let reader = new FileReader();
reader.onload = e => {
let img = new Image();
img.src = e.target.result;
img.onload = () => {
let imgsrc = common.compress(img);
this.$options.methods.uploadPic.bind(this)(imgsrc);
this.$refs.addPicFile.value = "";
};
};
reader.readAsDataURL(file);
},
uploadPic(data) {
let res = Http.getAxios("POST", `/image/upload`, data);
res.then(data => {
this.list.push({
src: data.message,
imgHover: false
});
this.$emit("addPic", this.list);
});
},
reset(index) {
this.list.splice(index, 1);
this.$emit("resetPic", this.list);
},
// 清空图片
clearPic() {
this.photoList = [];
this.$emit("clearPic", this.photoList);
}
},
mounted() {
// 因为修改调用查询方法返回过来的数据会慢一点,所以我延迟赋值了,否则图片将不会展示
setTimeout(() => {
this.photoList = this.photo;
this.list = this.photo;
}, 300);
}
};
</script>