前段时间刚入坑uni-app,就被分配到做图片上传的组件,所以就趁这个机会练练手

单张图片上传

多张图片上传

点击图片的效果

图片压缩原理是将图片画到canvas上面,使用Canvas压缩

上代码:

upload-image.vue(组件代码直接拷贝可用)

<template><view class="upload_image"><view class="list_box" :class="onePicClass" :style="{ minHeight: height + 'rpx'}"><view class="item" v-for="(item, index) in imgList" :key="index" :style="{ width: width + 'rpx', height: height + 'rpx'}"><image class="img_pre" :src="item" mode="aspectFit" :style="{ width: width + 'rpx', height: height + 'rpx'}" @click="imgPre(item)"></image><view class="del_btn" @click="delImg(index)"><view class="del_icon_wrap"><image class="del_icon" src="../static/images/del.png"></image></view></view></view><view class="add_btn" :class="addBtnClass" @click="addImg" v-if="imgList.length < maxCount"><view class="icon icon_camera" :style="{ width: width + 'rpx', height: height + 'rpx'}"><image class="camera_icon" src="../static/images/camera.png"></image></view></view></view><view class="canvas_view"><canvas id="firstCanvas" class="firstCanvas" canvas-id="firstCanvas" :style="{width: canvasWidth+'px', height: canvasHeight+'px'}"></canvas></view></view>
</template><script>export default {props: {maxCount: { // 最大上传数量type: Number,default: 1},iconType: { // 图标类型 camera plustype: String,default: 'camera'},sourceType: { // album 从相册选图,camera 使用相机type: Array,default: () => ['album', 'camera']},width: { //    宽 单位rpxtype: Number,default: 90},height: { // 高 单位rpxtype: Number,default: 90},maxSize: { // 图片最大大小type: Number,default: 8},sizeType: {type: Array,default: () => ['compressed']},quality: {type: Number,default: 0.6},},data() {return {imgList: [], // 图片列表uploadUrl: '', // 上传图片的服务器请求地址visiable: false, // 显示组件的标识context: undefined, // canvas 绘图上下文canvasWidth: 0, // 默认宽度 100px、高度 100pxcanvasHeight: 0,};},mounted() {this.context = uni.createCanvasContext('firstCanvas', this);},computed: {onePicClass() {return this.maxCount === 1 ? "one_pic" : "multi_pic";},addBtnClass() {return this.imgList.length != 0 && this.maxCount != 1 ? "add_margin" : ""}},methods: {imgPre(url) {//图片预览wx.previewImage({current: url, // 当前显示图片的http链接urls: this.imgList // 需要预览的图片http链接列表})},// 删除图片delImg(index) {uni.showModal({title: '',content: '确认删除当前图片?',success: (res) => {if (res.confirm) {this.imgList.splice(index, 1);this.$emit('imgListChange', this.imgList);uni.showToast({title: '删除成功!'});}}});},// 添加图片addImg() {// 从本地相册选择图片或使用相机拍照uni.chooseImage({count: 1,sourceType: this.sourceType, //从相册选择// sizeType: this.sizeType,success: (res) => {const tempFilePaths = res.tempFilePaths;const tempFiles = res.tempFiles[0];if (parseInt(tempFiles.size) > this.maxSize * 1024 * 1024) {uni.showToast({title: '图片过大,请确保上传图片小于8MB',icon: 'none'})} else {this.compressImg(tempFilePaths, [], 0);// this.uploadImg(tempFilePaths, 0);}},fail(err) {console.log(err)}});},// 压缩图片compressImg(tempFilePaths, compressPaths, index) {uni.showLoading({title: '图片上传中',mask: true});let i = index;let arr = [...compressPaths];uni.getImageInfo({src: tempFilePaths[i],success: (res) => {if (res) {let canvasWidth = res.width // 图片原始长宽let canvasHeight = res.height;this.canvasWidth = canvasWidth;this.canvasHeight = canvasHeight;// canvas宽高重新设置后会有一段渲染的间隔,这个间隔可能导致画到画布的图片出现大小不一致的bug,这里做下300ms延迟处理兼容setTimeout(() => {this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);this.context.drawImage(res.path, 0, 0, this.canvasWidth, this.canvasHeight);this.context.draw(false, () => {// 将图片画到canvas上面,使用Canvas压缩uni.canvasToTempFilePath({x: 0,y: 0,width: this.canvasWidth,height: this.canvasHeight,destWidth: this.canvasWidth,destHeight: this.canvasHeight,canvasId: 'firstCanvas',fileType: 'jpg',quality: this.quality,success: (res) => {// 在H5平台下,tempFilePath 为 base64i++;arr.push(res.tempFilePath);if (i < tempFilePaths.length) {this.compressImg(tempFilePaths, arr, i);} else {// 上传服务器this.uploadImg(arr, 0);}},fail: (err) => {uni.hideLoading();uni.showToast({title: '网络异常',icon: 'none'})}}, this);});}, 300);} else {uni.hideLoading();uni.showToast({title: '网络异常',icon: 'none'})}},fail: (err) => {uni.hideLoading();uni.showToast({title: '网络异常',icon: 'none'})}});},// 上传图片uploadImg(tempFilePaths, index) {let i = index;uni.uploadFile({url: `https://test.com/upload`,filePath: tempFilePaths[i],methods: 'POST',name: 'file',data: {path: tempFilePaths[i]},success: (res) => {uni.hideLoading()if (res.data.err) {uni.showToast({title: '网络异常',icon: 'none'})} else {if (res.data) {let data = JSON.parse(res.data);let url = Object.values(data)this.imgList = [...this.imgList, ...url];this.$emit('imgListChange', this.imgList);}}},fail: (err) => {uni.hideLoading()uni.showToast({title: '网络异常',icon: 'none'})}});}}}
</script><style scoped lang='scss'>.img_pre,.item,.icon {border-radius: 10rpx;}.item,.icon {border: 1rpx solid #e5e5e5;background-color: #ffffff;box-sizing: border-box;}.item {display: flex;align-items: center;justify-content: center;align-items: center;position: relative;margin: 0 10rpx;}/* 单照片上传,图片不需要边距 */.one_pic {.item {margin: 0 !important;}}/* 多图会有多行展示的情况,设置上下边距 */.multi_pic {.item,.icon {margin-top: 10rpx !important;margin-bottom: 10rpx !important;}}/* 多图,并且有上传图片,上传图片按钮要有边距 */.add_margin {margin: 0 10rpx !important;}.del_btn {position: absolute;top: -14rpx;right: -14rpx;width: 28rpx;height: 28rpx;.del_icon_wrap {width: 28rpx;height: 28rpx;display: inline-flex;align-items: center;justify-content: center;background-color: red;border-radius: 50%;position: absolute;.del_icon {width: 20rpx;height: 20rpx;}}}.list_box {width: 100%;height: 100%;display: flex;align-items: center;justify-content: flex-start;flex-wrap: wrap;}.canvas_view {opacity: 0;position: fixed;right: -10000rpx;bottom: -10000rpx;width: 0rpx;height: 0rpx;overflow: hidden;}.icon {display: flex;align-items: center;justify-content: center;.camera_icon {width: 50rpx;height: 37rpx;}}
</style>

调用:

<upload-image height="116" width="116" iconType="plus" @imgListChange="imgChange"></upload-image>

在methods中加上图片改变的回调事件

imgChange(data) {console.log("data:", data)
},

over

关于图片压缩的方法,欢迎交流欢迎指正

uni-app 图片上传组件 canvas压缩相关推荐

  1. 【微信小程序】图片上传组件“mp-uploader“(weui)

    使用示例   wxml <mp-uploader files="{{files}}" max-count="{{maximgs}}" max-size=& ...

  2. 移动端图片上传后进行压缩功能

    移动端图片上传后进行压缩功能 在进行讲解上传图片压缩之前,我们先来了解下HTML5中的文件上传的基本知识点. 一: FileList对象与file对象. FileList对象表示用户选择的文件列表.在 ...

  3. h5 php 拍照上传图片,H5拍照、选择图片上传组件核心

    背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render).遂进行了调研,发现很多的工具.但有的太大,有的使用麻烦,有的不满足使用需求.决 ...

  4. H5拍照、选择图片上传组件核心

    背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render).遂进行了调研,发现很多的工具.但有的太大,有的使用麻烦,有的不满足使用需求.决 ...

  5. php 图片压缩旋转,移动端图片上传旋转、压缩问题的解决方案

    本篇文章就给大家带来移动端图片上传旋转.压缩问题的解决方案.有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助. 前言 在手机上通过网页 input 标签拍照上传图片,有一些手机会出现图片 ...

  6. 如何上传图片到fileupload空间_如何用原生js写图片上传组件v2.0(还有新版本)?...

    js图片上传组件: 基本要求: 1.上传的图片可预览,可删除,可被覆盖更新 2.要求图片格式为jpg和png,大小不能超过2M 新加需求: 1.模拟回显,可用本地存储(实际上的回显是通过后台传过来的u ...

  7. antd的联级选择器异步调用编辑回显_react-uplod-img 是一个基于 React antd组件的图片上传组件...

    react-uplod-img 是一个基于 React antd组件的图片上传组件 支持oss qiniu等服务端自定义获取签名,批量上传, 预览, 删除, 图片精确的尺寸限制 排序等功能 需要 re ...

  8. 分享一个react 图片上传组件 支持OSS 七牛云

    react-uplod-img 是一个基于 React antd组件的图片上传组件 支持oss qiniu等服务端自定义获取签名,批量上传, 预览, 删除, 排序等功能 需要 react 版本大于 v ...

  9. antd vue3 图片上传组件扩展,支持多图上传 图片拖拽排序等

    组件涉及到 vue3.2.vite.Ant Design Vue 3.2.16.Windi CSS样式库.vuedraggable-es拖拽库等 组件功能 图片拖拽 多图上传 自定义图片加载样式 自定 ...

  10. vue2.0_实现图片上传前进行压缩(约10倍)

    前言 1.以VantUI组件库中van-uploader文件上传为例 2.本例以图片大于2M才开始压缩,压缩条件可自行调节 3.压缩完成得到图片的base64格式,可转换成file文件 4.读取到图片 ...

最新文章

  1. 20张图助你了解JVM运行时数据区,你还觉得枯燥吗?
  2. FD.io/VPP — ACL
  3. 原 layer父子页面交互
  4. Nginx负载均衡实现之用户手动选择与DNS轮询
  5. [PAT乙级]1046 划拳
  6. FileSystemMap:与文件系统交互的自然方法
  7. 弹出VIEW.非dialog
  8. html新增伪类,css3新增伪类有哪些
  9. docker下使用redis
  10. getobject java,Object get(Object obj)
  11. sublime text下 Python 问题:TabError: inconsistent use of tabs and spaces in indentation
  12. 在IDEA中,项目中出现红色波浪线解决办法
  13. Qi v1.2.4协议 之 10 Object Detection 【英文翻译】
  14. keil5点击调试提示SarmCM3.dll文件缺少问题
  15. 百度地图开发入门(4):散点图示例
  16. Automator——为mac创建自定义mac右键菜单
  17. bash+vasp+vaspkit能量应变计算弹性常数
  18. 打怪游戏 勇者打恶龙1.6(1.7)
  19. 微信小程序使用nginx跳转第三方url
  20. 男性健身全攻略 男人4大方法快速塑形

热门文章

  1. 计算机关机后,电脑关机后自动重启怎么解决?
  2. selenium 实战之 A级纳税人信息
  3. 编1加到100的代码用C语言,用C语言编写一个程序,计算从1加到100的和,并将结果输出。跪求代码,急!...
  4. MySQL相关知识整理
  5. 技术系统进化法则包括_八大技术系统进化法则主要包括哪些
  6. 京东后台:订单履约系统设计(上)
  7. 基于C++实现银行业务系统
  8. redis集群scan_Redis中的Scan命令的使用:查询大数据量
  9. Rasa 3.x 学习系列-Rasa 3.1+ ElasticSearch 8.2.0 对话机器人实战六
  10. html谷歌浏览器实现自动播报语音,vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法...