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

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= async(url)=> {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= async(url)=> {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= async(url)=> {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.mzph.cn/bicheng/56712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言 | Leetcode C语言题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; typedef struct {double radius;double x_center;double y_center; } Solution;Solution* solutionCreate(double radius, double x_center, double y_center) {srand((unsigned)time(NULL));Solution *obj (Solution *)malloc(sizeof(Sol…

论文阅读(十六):Deep Residual Learning for Image Recognition

文章目录 1.介绍2.基本原理3.两种残差块4.网络结构 论文&#xff1a;Deep Residual Learning for Image Recognition   论文链接&#xff1a;Deep Residual Learning for Image Recognition   代码链接&#xff1a;Github 1.介绍 在ResNet网络提出之前&#xff0c;传统的卷…

如何快速部署一套智能化openGauss测试环境

一、openGauss介绍 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行&#xff0c;允许用户自由地复制、使用、修改和分发软件。openGauss内核深度融合了华为在数据库领域多年的研发经验&#xff0c;结合企业级场景需求&#xff0c;持续构建竞争力…

基于SpringBoot+Vue+uniapp微信小程序的婚庆摄影小程序的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

在docker的容器内如何查看Ubuntu系统版本

文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境&#xff1a; docker 一、问题描述 由于 lsb_release -a 只能查看自己电脑&#xff08;宿主机&#xff09;的系统版本&#xff0c;如果在docker的容器内又应该如何查看Ubuntu系统版本呢&#xff…

机器学习—学习率的选择

如果你选择适当的学习率&#xff0c;你的学习算法将运行得更好&#xff0c;如果太小&#xff0c;它会跑得很慢&#xff0c;如果太大&#xff0c;它甚至可能不会收敛&#xff0c;那么如何为模型选择一个好的学习率呢&#xff1f; 如果绘制多次迭代的成本&#xff0c;注意到成本…

深度学习笔记20_数据增强

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 一、我的环境 1.语言环境&#xff1a;Python 3.9 2.编译器&#xff1a;Pycharm 3.深度学习环境&#xff1a;TensorFlow 2.10.0 二、GPU设置…

LLM实践--支线:拯救Continue Pretrain的数据

背景 首先介绍下什么是Continue Pretrain&#xff08;CP&#xff09;。CP 和 Pretrain、SFT一样指的是 LLM 训练的一个阶段&#xff0c;在前大模型时代还被称作Post Pretrain。CP 是在Pretrain和SFT之间的训练阶段&#xff0c;目的是为模型注入领域知识&#xff0c;这个领域是…

mqtt客户端订阅一直重复连接?

文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者&#xff0c;我们创造bug&#xff0c;传播bug&#xff0c;毫不留情地消灭bug&#xff0c;在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案&#xff0c;感兴…

解决使用MobaXterm不能向Ubuntu上传下载文件的问题

如上图所示 解决方案 新建连接&#xff0c;使用root账户建立ssh会话&#xff0c;就是建立会话的时候&#xff0c;用户名使用root。ubuntu系统默认不允许远程root账户建立连接&#xff0c;表现就是你新建ssh会话&#xff0c;在第一步输入root密码的时候&#xff0c;密码正确会报…

一文探索RareShop:首个面向消费者的RWA NFT商品发售平台

作者&#xff1a;Weilin&#xff0c;PANews 本轮牛市中&#xff0c;加密消费级应用正成为一种热门趋势&#xff0c;比如pump.fun和Polymarket等产品已成为C端用户的明星。加密货币正日益渗透到日常消费者的产品、服务和行为中。这意味着加密货币的使用不再局限于投机交易或去中…

appium启动hbuild打包的apk异常解决

目录 一、错误信息 二、问题解决 2.1 通过以下命令获取安装包名称&#xff1a; 2.2 这个launcher状态下的安装包名称和active&#xff0c;替换原先的安装包名称 一、错误信息 通过adb shell dumpsys activity | findstr "mResume" 命令获取的安装包信息&#xff…

从零开始学习OMNeT++系列第三弹——新建一个使用INET框架的工程

上一篇学习了如何新建一个omnet的工程&#xff0c;这篇来学习下INET框架以及如何使用INET框架来新建一个工程。 INET框架是什么 INET框架是一个开源模型库&#xff0c;用于OMNeT仿真环境。它为研究者和学生在使用通信网络时提供协议、代理和其他模型。当设计和验证新协议或探…

深入理解计算机系统--计算机系统漫游

对于一段最基础代码的文件hello.c&#xff0c;解释程序的运行 #include <stdio.h>int main() {printf ( "Hello, world\n") ;return 0; }1.1、信息就是位上下文 源程序是由值 0 和 1 组成的位&#xff08;比特&#xff09;序列&#xff0c;8 个位被组织成一组…

安防监控摄像头图传模组,1公里WiFi无线传输方案,监控新科技

在数字化浪潮汹涌的今天&#xff0c;安防监控领域也迎来了技术革新的春风。今天&#xff0c;我们就来聊聊这一领域的产品——摄像头图传模组&#xff0c;以及它如何借助飞睿智能1公里WiFi无线传输技术&#xff0c;为安防监控带来未有的便利与高效。 一、安防监控的新篇章 随着…

mysql--基本查询

目录 搞定mysql--CURD操作&#xff0c;细节比较多&#xff0c;不难&#xff0c;贵在多多练 1、Create--创建 &#xff08;1&#xff09;单行插入 / 全列插入 &#xff08;2&#xff09;插入否则替换 &#xff08;3&#xff09;替换 2、Retuieve--select 1&#xff09;全…

FreeRTOS - 软件定时器

在学习FreeRTOS过程中&#xff0c;结合韦东山-FreeRTOS手册和视频、野火-FreeRTOS内核实现与应用开发、及网上查找的其他资源&#xff0c;整理了该篇文章。如有内容理解不正确之处&#xff0c;欢迎大家指出&#xff0c;共同进步。 1. 软件定时器 软件定时器也可以完成两类事情…

JDK-23与JavaFX的安装

一、JDK-23的安装 1.下载 JDK-23 官网直接下载&#xff0c;页面下如图&#xff1a; 2.安装 JDK-23 2.1、解压下载的文件 找到下载的 ZIP 文件&#xff0c;右键点击并选择“解压到指定文件夹”&#xff0c;将其解压缩到您希望的目录&#xff0c;例如 C:\Program Files\Java\…

多进程思维导图

1> 思维导图 2> 使用父子进程完成两个文件的拷贝&#xff0c;父进程拷贝前一半&#xff0c;子进程拷贝后一半&#xff0c;两个进程同时进行&#xff08;君子作业&#xff09; #include <myhead.h> typedef struct sockaddr_in addr_in_t; typedef struct sockaddr…

毕业设计选题:基于django+vue的个人博客系统设计与开发

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 博主管理 博客文章管理 博文排行管理 博文打赏管理 博文…