uni-app 开发微信小程序,实现图片预览和保存

devtools/2024/10/25 16:19:54/

1.使用 uni.previewImage() 预览图片

1.1 图片列表

1.2 预览

1.2.1 样式无法调整

1.2.2 微信小程序不支持预览本地文件路径图片(图片上传到小程序的临时文件存储或云服务存储)

1.3 无法绑定 @longpress="saveImage(item)"  长按保存图片事件

1.4 前端代码

<template><view class="container"><view class="tabs"><uni-segmented-control:current="current":values="tabList"@clickItem="onClickItem"styleType="button"activeColor="#27BA9B"/></view><view class="content"><view v-show="current === 0"><view class="video"><videostyle="width: 100%;"src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4"enable-play-gesturev-for="item in 3"/></view></view><view v-show="current === 1"><scroll-view><view class="image-box" v-for="(item,index) in images"><view class="navigator" ><!-- @tap:点击事件, @longpress:长按事件 --><image class="image" :src="item" @tap="previewImage(index)" @longpress="saveImage(item)" /></view></view></scroll-view></view><view v-show="current === 2"><scroll-view><uni-card v-for="item in 10"><text>这是一个基础卡片示例,内容较少,此示例展示了一个没有任何属性不带阴影的卡片。</text></uni-card></scroll-view></view></view></view>
</template><script setup>import { ref,computed } from 'vue'const tabList=['视频', '图片', '文案']// 选中tab的下标const current = ref(0)// 选中的图片indexconst activeIndex = ref(0)// 切换tabconst onClickItem= (e)=>{current.value = e.currentIndex}// 图片列表// 微信小程序 uni.previewImage() 不支持使用本地文件路径预览图片,可上传到小程序的临时文件存储或云服务存储const images = ref(["https://ww2.sinaimg.cn/mw690/008a4fzDgy1hrc5rdztg7j30zk24ykfc.jpg", // 云服务存储"https://ww4.sinaimg.cn/mw690/005QiJkMgy1hrpsfxno4rj30zu25odq0.jpg", // 云服务存储"https://wx1.sinaimg.cn/mw690/005UJ76vgy1hrh4zt0k1ij30v91votw9.jpg", // 云服务存储"https://wx1.sinaimg.cn/mw690/60ed0cf7ly1hs8msnz6e6j20zu25o16d.jpg", // 云服务存储"/static/images/beauty1.jpg", // 本地文件存储])// uni.previewImage() 图片预览const previewImage= (index)=>{uni.previewImage({urls: images.value,current: images.value[index], // 当前显示图片的链接});}// 保存图片const saveImage= (url)=> {// 确认框uni.showModal({content: '下载该图片?',confirmColor: '#27BA9B',success: async(res) => {if (res.confirm) {try {let filePath;if (url.startsWith('/')) {filePath = url; // 本地图片路径,可直接保存} else {const result = await uni.downloadFile({ url }); // 云服务图片地址,要先下载filePath = result.tempFilePath;  // 本地临时存储路径}await uni.saveImageToPhotosAlbum({ filePath });uni.showToast({ title: '保存成功', icon: 'success', duration: 2000 });} catch (err) {console.error('保存失败:', err);}}},})}
</script><style lang="less" scoped>
.container{display: flex;flex-direction: column;height: 100vh;background-color: #fff;.tabs{padding: 10px;}.content{flex: 1;overflow-y: auto;.video{margin: 10px;}.image-box{display: inline-flex; // 使用 flex 布局,并且作为行内元素margin: 0 5px;width: 30%;.navigator{display: flex;width: 100%;}}}
}
</style>

2.使用自定义组件预览图片

2.1 图片列表

2.2 预览(可预览云服务存储和本地存储的图片

2.3 长按保存

2.4 前端代码

2.4.1 自定义预览组件<Preview />

<!-- 图片预览组件 -->
<template><view class="container"><view class="fullscreen" ><swiper class="fullscreen-swiper" :current="activeIndexValue" @change="handleSwiperChange" circular><swiper-item class="swiper-item" v-for="(item, index) in imageListValue" :key="index"><image :src="item" @longpress="saveImage(item)" mode="scaleToFill" style="width: 100vw; height: 100vh;"  /></swiper-item></swiper><view class="number">{{ activeIndexValue+1 }}/{{ imageListValue.length }}</view><button class="btn" type="default" @tap="emit('close')">退出全屏</button></view></view>
</template><script setup>import { ref, onMounted } from 'vue';import { onLoad } from '@dcloudio/uni-app'// 子调父,退出预览模式const emit = defineEmits()// 获取父组件的参数,activeIndex:选中的索引,imageList:图片url列表let query = defineProps(["activeIndex","imageList"])let activeIndexValue = ref(query.activeIndex)let imageListValue = ref(query.imageList)// 要保存图片的urlconst url = ref('');// 获取屏幕边界到安全区域距离const { safeAreaInsets } = uni.getSystemInfoSync()// 处理 swiper change 事件const handleSwiperChange = (event) => {activeIndexValue.value = event.detail.current;url.value = imageListValue.value[activeIndexValue.value];};// 保存图片const saveImage= (url)=> {// 确认框uni.showModal({content: '下载该图片?',confirmColor: '#27BA9B',success: async(res) => {if (res.confirm) {try {let filePath;if (url.startsWith('/')) {filePath = url; // 本地图片路径,可直接保存} else {const result = await uni.downloadFile({ url }); // 云服务图片地址,要先下载filePath = result.tempFilePath;  // 本地临时存储路径}await uni.saveImageToPhotosAlbum({ filePath });uni.showToast({ title: '保存成功', icon: 'success', duration: 2000 });} catch (err) {console.error('保存失败:', err);}}},})}
</script><style lang="less" scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f4f4f4;
}.swiper {height: 100%;width: 100%;border: 1px solid #ccc;overflow: hidden;
}.swiper-item {height: 100%;display: flex;justify-content: center;align-items: center;
}.fullscreen {position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: center;z-index: 1000;background-color: rgba(0, 0, 0, 0.8);
}.fullscreen-swiper {width: 100%;height: 100%;
}.number{position: absolute;top: 20px;left: 50%;transform: translateX(-50%);color: #fff;background-color: rgba(0, 0, 0, 0.2);padding: 5px 10px;border-radius: 20px;
}.btn {position: absolute;bottom: 20px;left: 50%;transform: translateX(-50%);color: #ccc;background-color: rgba(0, 0, 0, 0.2);
}
</style>

2.4.2 使用自定义预览组件<Preview />

<template><view class="container"><view class="tabs"><uni-segmented-control:current="current":values="tabList"@clickItem="onClickItem"styleType="button"activeColor="#27BA9B"/></view><view class="content"><view v-show="current === 0"><view class="video"><videostyle="width: 100%;"src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4"enable-play-gesturev-for="item in 3"/></view></view><view v-show="current === 1"><scroll-view><view class="image-box" v-for="(item,index) in images"><!-- @tap:点击事件, @longpress:长按事件 --><view class="navigator" @tap="preview(index)" ><image class="image" :src="item" @longpress="saveImage(item)" /></view></view></scroll-view></view><view v-show="current === 2"><scroll-view><uni-card v-for="item in 10"><text>这是一个基础卡片示例,内容较少,此示例展示了一个没有任何属性不带阴影的卡片。</text></uni-card></scroll-view></view></view></view><!-- 自定义预览组件 --><Preview class="container" v-if="previewFlag" :activeIndex="activeIndex" :imageList="images" @close="close" />
</template><script setup>import { ref,computed } from 'vue'const tabList=['视频', '图片', '文案']// 选中tab的下标const current = ref(0)// 是否是预览模式let previewFlag = ref(false);// 选中的图片indexconst activeIndex = ref(0)// 子组件调用父组件的关闭预览const close = ()=>{previewFlag.value = false}// 点击开启预览模式const preview= (index)=>{previewFlag.value = trueactiveIndex.value = index}// 切换tabconst onClickItem= (e)=>{current.value = e.currentIndex}// 图片列表// 微信小程序 uni.previewImage() 不支持使用本地文件路径预览图片,可上传到小程序的临时文件存储或云服务存储const images = ref(["https://ww2.sinaimg.cn/mw690/008a4fzDgy1hrc5rdztg7j30zk24ykfc.jpg", // 云服务存储"https://ww4.sinaimg.cn/mw690/005QiJkMgy1hrpsfxno4rj30zu25odq0.jpg", // 云服务存储"https://wx1.sinaimg.cn/mw690/005UJ76vgy1hrh4zt0k1ij30v91votw9.jpg", // 云服务存储"https://wx1.sinaimg.cn/mw690/60ed0cf7ly1hs8msnz6e6j20zu25o16d.jpg", // 云服务存储"/static/images/beauty1.jpg", // 本地文件存储])// 保存图片const saveImage= (url)=> {// 确认框uni.showModal({content: '下载该图片?',confirmColor: '#27BA9B',success: async(res) => {if (res.confirm) {try {let filePath;if (url.startsWith('/')) {filePath = url; // 本地图片路径,可直接保存} else {const result = await uni.downloadFile({ url }); // 云服务图片地址,要先下载filePath = result.tempFilePath;  // 本地临时存储路径}await uni.saveImageToPhotosAlbum({ filePath });uni.showToast({ title: '保存成功', icon: 'success', duration: 2000 });} catch (err) {console.error('保存失败:', err);}}},})}
</script><style lang="less" scoped>
.container{display: flex;flex-direction: column;height: 100vh;background-color: #fff;.tabs{padding: 10px;}.content{flex: 1;overflow-y: auto;.video{margin: 10px;}.image-box{display: inline-flex; // 使用 flex 布局,并且作为行内元素margin: 0 5px;width: 30%;.navigator{display: flex;width: 100%;}}}
}
</style>


http://www.ppmy.cn/devtools/128719.html

相关文章

微信消息语音播报秒实现

1. 监听系统消息通知 注册一个监听系统消息的服务 <serviceandroid:name".MyNotificationListenerService"android:exported"true"android:permission"android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" ><intent-filter>&…

FFmpeg 库的简要说明

FFmpeg 库的简要说明&#xff1a; libavutil 功能&#xff1a;提供一系列通用工具函数&#xff0c;旨在简化开发流程。 主要用途&#xff1a; 随机数生成器&#xff1a;用于生成随机数&#xff0c;适用于各种应用。 数据结构&#xff1a;提供常用的数据结构&#xff08;如链表…

[Linux网络编程]04-多进程/多线程并发服务器思路分析及实现(进程,信号,socket,线程...)

一.思路 实现一个服务器可以连接多个客户端&#xff0c;每当accept函数等待到客户端进行连接时 就创建一个子进程; 核心思路&#xff1a;让accept循环阻塞等待客户端&#xff0c;每当有客户端连接时就fork子进程&#xff0c;让子进程去和客户端进行通信&#xff0c;父进程用于…

骨传导耳机哪个品牌好用质量好?2024年五款高性价比骨传导耳机推荐

骨传导耳机是我们日常生活中不可或缺的电子产品之一&#xff0c;无论是为了享受音乐还是运动健身使用都非常的合适&#xff0c;而选择一款好用且质量优秀的骨传导耳机却并不简单。因为市面上的骨传导耳机品牌琳琅满目&#xff0c;各种功能和设计让人眼花缭乱&#xff0c;经常让…

基于RK3588/算能BM1684 AI盒子:综合视频智能AI分析系统建设方案(五)边缘盒子与AI服务器

方案硬件介绍 智能AI分析服务器 机型:2U机架式服务器 处理器&#xff1a;CPU_Xeon_5318Y_2.1GHz_24C_48T_165W*2 内存&#xff1a;32GB DDR4 3200 RDIMM*4 240GB 2.5in&#xff08;SATA SSD&#xff09;*1 硬盘&#xff1a;6 TB, SATA 6Gb/s, 7.2K&am…

《近似线性可分支持向量机的原理推导》 目标函数 公式解析

本文是将文章《近似线性可分支持向量机的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 公式 9-38 解释&#xff1a; min ⁡ w , b , ξ 1 2 ∥ w ∥ 2 C ∑ i 1 N ξ i \min_{w, b, \xi} \quad \frac{1}{2} \|w\|^2 C \sum_{i1}^{N} \x…

Python爬虫:自动化获取商品评论数据

为什么选择Python爬虫API 高效的数据处理&#xff1a;Python的数据处理能力&#xff0c;结合Pandas等库&#xff0c;可以轻松处理和分析大量的评论数据。丰富的库支持&#xff1a;Python拥有丰富的库&#xff0c;如requests用于发送HTTP请求&#xff0c;BeautifulSoup用于解析…

Swift Macro 在业务开发中的探索与实践

简介 Swift Macro 在 Swift 5.9 版本中正式引入&#xff0c;且需配合 Xcode 15 使用。Swift Macro 作为一种新的设计方法&#xff0c;致力于帮开发者降低编写重复代码的繁琐&#xff0c;以更为简洁优雅的方式去实现。 在 OC 中&#xff0c;有大家熟知的宏 #define&#xff0c;…