移动端图片裁剪、压缩后上传
<template>
<div id="app">
<div class="content" ref="content">
<!-- 上传 -->
<input
class="upload"
type="file"
ref="upload"
name="upload"
accept="image/*"
@change="upload"
>
<!-- 上传的按钮 -->
<button @click="uploadImage">上传图片</button>
<!-- 预览 -->
<img :src="imgUrl " alt ref="image">
</div>
<!-- 裁剪 -->
<div class="v-cropper-layer cropper-box" ref="layer" style="display:none;">
<div class="layer-header cropper-position">
<button class="cancel" @click="cancelHandle">取消</button>
<button class="confirm" @click="confirmHandle">裁剪</button>
</div>
<img ref="cropperImg">
</div>
</div>
</template>
<script>
import Cropper from "cropperjs"; // 裁剪插件,需要通过npm安装下
// require("@/assets/plugin/localResizeIMG/lrz.bundle.js"); https://www.npmjs.com/package/lrz
import lrz from "lrz"; // 压缩库,需要通过npm安装下
export default {
data() {
return {
cropper: {},
fileName: "",
imgUrl: ""
};
},
methods: {
dataURLtoFile(dataurl, filename) {
//将base64转换为文件
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 });
},
random_string(len) {
// 随机生成文件名
len = len || 32;
var chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
var maxPos = chars.length;
var pwd = "";
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
},
upload(e) {
// 上传事件,当input选取图片或更改图片时触发
let file = e.target.files[0];
this.fileName = file["name"];
let URL = window.URL || window.webkitURL;
this.$refs["layer"].style.display = "block";
this.$refs["content"].style.display = "none";
this.cropper.replace(URL.createObjectURL(file));
},
uploadImage() {
// 触发upload方法
this.$refs.upload.click();
},
cropperInit() {
// 初始化裁剪插件
let cropperImg = this.$refs["cropperImg"];
this.cropper = new Cropper(cropperImg, {
aspectRatio: 1 / 1, // 裁剪配置,具体见https://blog.csdn.net/weixin_38023551/article/details/78792400
viewMode: 1,
dragMode: "move"
});
},
cancelHandle() {
// 取消上传
this.cropper.reset();
this.$refs["layer"].style.display = "none";
this.$refs["content"].style.display = "block";
this.$refs["upload"].value = "";
},
confirmHandle() {
// 确定上传
let cropBox = this.cropper.getCropBoxData();
let scale = 1;
let cropCanvas = this.cropper.getCroppedCanvas({
width: cropBox.width * scale,
height: cropBox.height * scale
});
let imgData = cropCanvas.toDataURL("image/jpeg");
// 上传用formData格式,具体方式视后台接口
let formdata = new FormData();
lrz(imgData, {
width: 300 // lrz为压缩方法,通过第31行文件的方式引入,安卓会有兼容问题,这里使用npm安装,兼容待检验,此处设置压缩参数,单位px
}).then(rst => {
// 处理成功后执行
formdata.append(
"files", // 此处配置传给后台的参数名
this.dataURLtoFile(rst.base64, this.random_string()) //base64转成文件格式并生成随机名字
);
reqUploadImg(formdata)
// 调接口时,上传的headers一定要配置
.then(res => {
this.imgUrl = res.results;
// 到此上传预览成功,以下为上传头像时的配置代码
var imgShow = this.$refs.image[0]; // 获取图片元素设置动态属性,此处处理在图片长宽不确定但父元素长宽固定时(如头像),始终全部展现
// 创建实例对象获取图片真实宽高
var newImg = new Image();
newImg.src = this.imgUrl;
// 等待图片加载完成获取宽高
newImg.onload = () => {
// 宽高适配
if (newImg.width >= newImg.height) {
imgShow.style["max-width"] = "";
imgShow.style["min-height"] = "";
imgShow.style["min-width"] = "0.6rem";
imgShow.style["max-height"] = "0.6rem";
} else {
imgShow.style["min-width"] = "";
imgShow.style["max-height"] = "";
imgShow.style["max-width"] = "0.6rem";
imgShow.style["min-height"] = "0.6rem";
}
};
mui.toast("上传成功", { duration: "short", type: "div" });
})
.catch(err => {
this.cancelHandle();
mui.toast("上传失败", { duration: "short", type: "div" });
});
});
}
},
mounted() {
this.cropperInit();
}
};
</script>
<style scoped>
/* 样式根据需要设置 */
.upload {
display: none;
}
.cropper-box {
width: 100%;
height: 100vh;
}
.cropper-box .cropper-position {
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
padding: 0.1rem 0;
z-index: 999;
background-color: #fff;
}
.cropper-position button:nth-of-type(2) {
background-color: #eb4242;
color: #fff;
border: none;
}
</style>