1.使用 uni.previewImage() 预览图片
1.1 图片列表
1.2 预览
1.2.1 样式无法调整
1.2.2 微信小程序不支持预览本地文件路径图片(图片上传到小程序的临时文件存储或云服务存储)
1.3 无法绑定 @longpress="saveImage(item)" 长按保存图片事件
1.4 前端代码
html
复制代码
<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">
<video
style="width: 100%;"
src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4"
enable-play-gesture
v-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)
// 选中的图片index
const activeIndex = ref(0)
// 切换tab
const 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 />
html
复制代码
<!-- 图片预览组件 -->
<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)
// 要保存图片的url
const 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 />
html
复制代码
<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">
<video
style="width: 100%;"
src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4"
enable-play-gesture
v-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);
// 选中的图片index
const activeIndex = ref(0)
// 子组件调用父组件的关闭预览
const close = ()=>{
previewFlag.value = false
}
// 点击开启预览模式
const preview= (index)=>{
previewFlag.value = true
activeIndex.value = index
}
// 切换tab
const 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>