使用 ionic + cordova + vue3 实现相册选择、拍照,并上传、预览图片

编程入门 行业动态 更新时间:2024-10-26 12:32:03

使用 ionic + cordova + vue3 实现相册选择、拍照,并<a href=https://www.elefans.com/category/jswz/34/1771255.html style=上传、预览图片"/>

使用 ionic + cordova + vue3 实现相册选择、拍照,并上传、预览图片

目录

1.上传组件 upload.vue

1.1 模板规划

1.2 点击添加按钮

1.2.1 实现询问弹框

1.2.2 实现拍照 

1.2.3 实现相册选择

 1.2.4 实现文件上传

1.2.5 校验图片类型并上传

1.2.6 获取图片列表

1.2.7 在组件内 添加图片附件

2.图片放大组件 enlarge-image.vue

2.1 点击图片放大

2.2 模板规划

2.3 使用 swiper11 踩坑的过程


1.上传组件 upload.vue

1.1 模板规划

模板包含三部分:

  • 已经上传的图片列表展示,若只读,则不展示删除按钮,每个图片点击后都可以被放大
  • 添加按钮展示,若没有图片,并且非只读,则展示
  • 暂无图片提示
  <div class="t-upload"><ion-grid><!-- {{ fileList }} --><!-- 已经上传的图片 --><template v-if="fileList?.length"><ion-col v-for="(img, index) in fileList" :key="img?.FILE_ID" size="4"><imgclass="file":src="getImgUrl(img)"alt=""@click="goEnlargeImage(index)"/><imgv-if="!readonly"class="delete"src="@/assets/image/common/upload-delete.png"@click.stop="removeFile(img?.FILE_ID)"/></ion-col></template><!-- 添加图片按钮 --><template v-if="!readonly"><ion-col v-if="!fileList?.length || fileList?.length < 9" size="4"><imgclass="add-file"src="@/assets/image/common/upload-add.png"@click="addMediaFile()"/></ion-col></template><template v-if="!fileList?.length && readonly"><div class="fs-14">暂无附件</div></template></ion-grid></div>

1.2 点击添加按钮

点击添加按钮后,会出现一个弹框,让用户选择图片来源:

  • 拍照
  • 相册选择

1.2.1 实现询问弹框

这个很简单,使用 ionic 的 actionSheetController 即可实现,根据用户的选择,决定执行的方法

  async addFile(max: number, callback: any) {const actionSheet = await actionSheetController.create({header: '附件类型选择',buttons: [{text: '拍照',handler: () => {this.camera({quality: 100,destinationType: 1,sourceType: 1,targetWidth: 1080,targetHeight: 1920,mediaType: 0,encodingType: 1,}).then(async (res) => {callback(res, 'photo');}).catch((err) => {publicService.toast('拍照失败,请重试');});},},{text: '相册',handler: () => {this.slectImagePicker({maximumImagesCount: max,quality: 50,}).then((res) => {callback(res, 'img');}).catch(() => {publicService.toast('相册打开失败');});},},{text: '取消',role: 'cancel',handler: () => {console.error('Cancel clicked');},},],});await actionSheet.present();}

1.2.2 实现拍照 

安装 cordova 插件:

  • @awesome-cordova-plugins/camera@6.4.0
  • cordova-plugin-camera@7.0.0

容易出现的问题:在真机调试时,点击拍照,提示我传入了非法参数

解决方案:升级 camera 插件版本,原来用的版本是 4.1.4,升级到 7.0.0 后 自动解决问题 

此方法最终返回一个图片对象信息

// 用于拍照或从相册选择照片
import { Camera, CameraOptions } from '@awesome-cordova-plugins/camera';/*** 拍照* @param opts 拍照配置* @returns*/camera(opts: CameraOptions): Promise<any> {return new Promise((resolve, reject) => {Camera.getPicture(opts).then((res: ChooserResult) => {resolve(res);}).then((error) => {reject('native camera error');});});}

1.2.3 实现相册选择

安装 cordova 插件:

  • @awesome-cordova-plugins/image-picker@6.4.0
  • cordova-plugin-telerik-imagepicker@2.3.6

容易出现的问题:在相册选择界面中,确认取消按钮是英文

解决方案:在 node_modules 里,找插件源码中的 xml 文件,搜索相关英文单词,改成中文

此方法最终返回一组图片对象信息

// 用于从相册中选择照片
import { ImagePicker, ImagePickerOptions } from '@awesome-cordova-plugins/image-picker';/*** 照片选择* @param opts* @returns*/slectImagePicker(opts: ImagePickerOptions): Promise<any> {// console.log('照片选择 ImagePicker ---', ImagePicker);return new Promise((resolve, reject) => {ImagePicker.getPictures(opts).then((res) => {resolve(res);}).catch(() => {reject('slectImagePicker native error');});});}

 1.2.4 实现文件上传

安装 cordova 插件:

  • @awesome-cordova-plugins/file-transfer@6.4.0
  • cordova-plugin-file-transfer@1.7.1

容易出现的问题:

  • 若接口返回的数据不是 JSON 对象,而是 map 对象,则容易解析失败
  • 服务器上的文件名字,需要保证唯一性
  • 给 file-transfer 插件传递的服务器地址,需要使用 encodeURI 进行编码
  • file-transfer 插件会把 给接口的文件流参数,默认存到 file 里,可以通过 fileKey 指定参数名

解决方案:

  • 接口返回的数据 最终会在 res.response 中存储,这是插件替我们封装了一层,让后端把返回的数据写成 JSON 对象的格式
  • 使用时间戳保证名字唯一性,new Date().getTime() + (name || `${pathArr[pathArr.length - 1]}`)
  • 编码服务器地址:encodeURI(API.uploadFile.serviceApi)
  • fileKey: 'form_file', // 表单元素名称,默认为 file,也可以和后端协商,文件流会存储在这个变量中

// 文件上传下载
import {FileTransfer,FileUploadOptions,
} from '@awesome-cordova-plugins/file-transfer';/*** 文件上传* @param fileUrl 文件路径* @param url 服务器地址* @param opts 配置项* @returns*/fileLoad(fileUrl: string,url: string,opts: FileUploadOptions): Promise<any> {return new Promise((resolve, reject) => {// 创建文件上传实例const file = FileTransfer.create();file.upload(fileUrl, url, opts, false).then((res) => {publicService.closeLoading(this.loading);this.loading = null;resolve(res);}).catch((err) => {console.log('文件上传错误 native ---', err);publicService.closeLoading(this.loading);this.loading = null;reject('文件上传发生错误');});});}

1.2.5 校验图片类型并上传

    /*** 文件上传* @param fileUrl 附件地址* @paramascriptionTypename 附件名称*/function fileUpload(fileUrl: string, name?: string) {// 获取文件名称const pathArr = state.fileUrl.split('?')[0].split('/') || '';// 文件格式后缀const suffix = state.fileUrl.substring(state.fileUrl.lastIndexOf('.') + 1);// 文件格式后缀const suffixs = ['png', 'jpg', 'jpeg', 'svg'];// 文件类型验证  通过后再上传文件let fileTypeValidate = true;if (state.fileUrl && !suffix) {fileTypeValidate = false;toast('不支持的文件类型');} else if (!suffixs.includes(suffix)) {fileTypeValidate = false;toast(`不支持${suffix}文件类型`);}// 若文件格式不合法,则不进行上传if (!fileTypeValidate) {if (publicService.loading) {publicService.closeLoading(publicService.loading);publicService.loading = null;}return;}// 获取文件名称const fileName = new Date().getTime() + (name || `${pathArr[pathArr.length - 1]}`);nativeService.fileLoad(fileUrl, encodeURI(API.uploadFile.serviceApi), {fileName, // 将文件保存在服务器上时,要使用的文件名fileKey: 'form_file', // 表单元素名称,默认为 file,也可以和后端协商,文件流会存储在这个变量中httpMethod: 'POST', // 上传接口请求方式params: {// 业务数据ID(用于业务关联附件)businessKey: props.businessKey,// 表单ID(可为空)- 分组inputFileId: props.inputFileId,// 文件form_file: fileUrl,// 登录用户createUser: userInfos.userId,},}).then((res) => {console.log('upload.vue 上传接口响应 ---', res.response);const testJX = JSON.parse(res.response);console.log('尝试解析 ---', testJX);if (publicService.loading) {publicService.closeLoading(publicService.loading);publicService.loading = null;}// 获取文件列表getFiles();}).catch((err) => {console.error(err);});}

1.2.6 获取图片列表

获取图片列表 getFiles 的几个场景:

  • 上传成功后
  • 删除成功后
  • 组件初始化的时候
  • watch 监听到 给接口传递的业务参数 发生变化后,比如 businessKey

每次获取了图片列表后,都应该 emit 最新的图片列表信息

 

1.2.7 在组件内 添加图片附件

上面说过,拍照返回的是一个图片信息,相册选择返回的是一组图片信息

根据返回信息的类型,可以拿到图片在手机本地的路径、名称,并依次调用文件上传

nativeService.addFile(9 - state.fileList.length,(res: any, fileType: string, name?: string) => {if (fileType === 'photo') {publicService.loading = publicService.sloading('拍照上传中,请稍候...');state.fileUrl = res;// 文件上传fileUpload(res, name || '');} else if (Array.isArray(res)) {if (res.length) {publicService.loading = publicService.sloading('相册选择照片上传中,请稍候...');}res.forEach(async (item, index1) => {state.fileUrl = item;state.fileName = name || '';// 文件上传await fileUpload(item, name || '');});} else {publicService.loading = publicService.sloading('附件上传中,请稍候...');state.fileUrl = res;state.fileName = name || '';// 文件上传fileUpload(res, name || '');}}
);

2.图片放大组件 enlarge-image.vue

2.1 点击图片放大

使用 ionic modalController 创建一个弹框页面

在方法内部传入 图片放大组件、组件需要的各种参数、默认展示的图片索引 等信息

    /*** 打开图片预览界面* @param index 当前点击的图片索引*/async function goEnlargeImage(index: number) {// console.log('t-upload.vue 点击的图片索引 ---', index);const modal = await modalController.create({component: EnlargeImage as any,componentProps: {pictures: state.fileList,initialSlide: index,time: new Date().getTime() + '',},cssClass: 'enlarge-image-modal',});await modal.present();}

2.2 模板规划

因为博主使用的是 ionic7,已经不存在 ion-slide 等组件了

通过官网提示 Vue Slides Guide: How to Get Swiper for Vue on Ionic Apps,决定使用 swiper 插件实现需求

组件接受俩参数:

  • 图片列表 pictures,在组件里用计算属性 stateImageList 进行关联,保证单项数据流
  • 当前激活的图片索引 initialSlide,默认为 0,和 swiper 的 initialSlide 属性关联绑定

模板如下:

  <ion-page><ion-header><ion-toolbar color="primary"><ion-buttons slot="end" @click="closePage()"><ion-icon class="close-icon" :icon="close"></ion-icon></ion-buttons></ion-toolbar></ion-header><ion-content><swiper :initialSlide="initialSlide" @transitionStart="start($event)"><swiper-slide v-for="(item, index) in stateImageList" :key="index"><!-- <div class="img-title">{{ item.FILE_NAME }}</div> --><div class="img-box" :style="{ 'max-height': maxHeight }"><imgv-if="!item.FILE_SUFFIX.toLowerCase() ||(item.FILE_SUFFIX.toLowerCase() !== 'mp4' &&item.FILE_SUFFIX.toLowerCase() !== 'mp3')":src="getImgUrl(item)":style="{ 'max-height': maxHeight }"/></div><!-- {{ getImgUrl(item) }} --></swiper-slide></swiper></ion-content></ion-page>

2.3 使用 swiper11 踩坑的过程

ionic 官网说的安装 swiper:npm install swiper@latest

执行了这个命令,npm 只会给你装上 swiper/vue,没给你装 swiper/modules,这样问题非常大,因为 Navigation, Pagination 等模块必须安装 swiper/modules,才能进行引入,咱需要手动安装哦

引入 swiper 相关内容:

// swiper
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Navigation, Pagination } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import '@ionic/vue/css/ionic-swiper.css';// 响应式变量const state = reactive({// swiper 扩展模块// modules: [Navigation, Pagination],// 最大高度maxHeight: window.innerHeight - 100,});// 图片列表const stateImageList = computed(() => {return JSON.parse(JSON.stringify(props.pictures));});function start(ev: any) {// console.log('ev ---', ev, stateImageList.value);}/*** 关闭当前页面*/function closePage() {modalController.dismiss();}

更多推荐

使用 ionic + cordova + vue3 实现相册选择、拍照,并上传、预览图片

本文发布于:2023-12-03 10:29:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1654340.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:上传   相册   图片   ionic   cordova

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!