鴻蒙OSUniApp制作一個小巧的圖片瀏覽器#三方框架 #Uniapp

利用UniApp制作一個小巧的圖片瀏覽器

最近接了個需求,要求做一個輕量級的圖片瀏覽工具,考慮到多端適配的問題,果斷選擇了UniApp作為開發框架。本文記錄了我從0到1的開發過程,希望能給有類似需求的小伙伴一些參考。

前言

移動互聯網時代,圖片已成為人們日常生活中不可或缺的內容形式。無論是社交媒體還是工作溝通,我們每天都會接觸大量圖片。因此,一個好用的圖片瀏覽器對用戶體驗至關重要。

UniApp作為一個使用Vue.js開發所有前端應用的框架,可以實現一套代碼、多端運行(iOS、Android、H5、小程序等),是開發跨平臺應用的理想選擇。今天我就分享一下如何使用UniApp開發一個小巧但功能完善的圖片瀏覽器。

開發環境準備

首先,我們需要搭建UniApp的開發環境:

  1. 安裝HBuilderX(官方IDE)
  2. 創建UniApp項目
  3. 配置基礎項目結構
# 如果使用CLI方式創建項目
npx @vue/cli create -p dcloudio/uni-preset-vue my-image-browser

項目結構設計

為了保持代碼的可維護性,我將項目結構設計如下:

├── components            # 組件目錄
│   ├── image-previewer   # 圖片預覽組件
│   └── image-grid        # 圖片網格組件
├── pages                 # 頁面
│   ├── index             # 首頁
│   └── detail            # 圖片詳情頁
├── static                # 靜態資源
├── utils                 # 工具函數
└── App.vue、main.js等    # 項目入口文件

核心功能實現

1. 圖片網格列表

首先實現首頁的圖片網格列表,這是用戶進入應用的第一個界面:

<template><view class="container"><view class="header"><text class="title">圖片瀏覽器</text></view><view class="image-grid"><view class="image-item" v-for="(item, index) in imageList" :key="index"@tap="previewImage(index)"><image :src="item.thumb || item.url" mode="aspectFill"lazy-load></image></view></view><view class="loading" v-if="loading"><text>加載中...</text></view></view>
</template><script>
export default {data() {return {imageList: [],page: 1,loading: false}},onLoad() {this.loadImages()},// 下拉刷新onPullDownRefresh() {this.page = 1this.imageList = []this.loadImages(() => {uni.stopPullDownRefresh()})},// 上拉加載更多onReachBottom() {this.loadImages()},methods: {// 加載圖片數據loadImages(callback) {if (this.loading) returnthis.loading = true// 這里可以替換為實際的API請求setTimeout(() => {// 模擬API返回數據const newImages = Array(10).fill(0).map((_, i) => ({id: this.imageList.length + i + 1,url: `https://picsum.photos/id/${this.page * 10 + i}/500/500`,thumb: `https://picsum.photos/id/${this.page * 10 + i}/200/200`}))this.imageList = [...this.imageList, ...newImages]this.page++this.loading = falsecallback && callback()}, 1000)},// 預覽圖片previewImage(index) {const urls = this.imageList.map(item => item.url)uni.previewImage({urls,current: urls[index]})}}
}
</script><style>
.container {padding: 20rpx;
}.header {height: 80rpx;display: flex;align-items: center;justify-content: center;margin-bottom: 20rpx;
}.title {font-size: 36rpx;font-weight: bold;
}.image-grid {display: flex;flex-wrap: wrap;
}.image-item {width: 33.33%;padding: 5rpx;box-sizing: border-box;
}.image-item image {width: 100%;height: 220rpx;border-radius: 8rpx;
}.loading {text-align: center;margin: 30rpx 0;color: #999;
}
</style>

這段代碼實現了圖片瀑布流展示、下拉刷新和上拉加載更多功能。我使用了懶加載技術來優化性能,同時使用縮略圖先加載,提升用戶體驗。

2. 自定義圖片預覽組件

雖然UniApp內置了圖片預覽功能,但為了實現更豐富的交互和動畫效果,我決定自己封裝一個圖片預覽組件:

<template><viewclass="image-previewer"v-if="visible"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"><view class="previewer-header"><text class="counter">{{ current + 1 }}/{{ images.length }}</text><view class="close" @tap="close">×</view></view><swiperclass="swiper":current="current"@change="handleChange":circular="true"><swiper-item v-for="(item, index) in images" :key="index"><movable-area class="movable-area"><movable-viewclass="movable-view":scale="item.scale":scale-min="1":scale-max="4":scale-value="item.scale"direction="all"@scale="handleScale($event, index)"@change="handleMoveChange"><image:src="item.url"mode="widthFix"@load="imageLoaded(index)"></image></movable-view></movable-area></swiper-item></swiper><view class="previewer-footer"><view class="save-btn" @tap="saveImage">保存圖片</view></view></view>
</template><script>
export default {name: 'ImagePreviewer',props: {urls: {type: Array,default: () => []},current: {type: Number,default: 0},visible: {type: Boolean,default: false}},data() {return {images: [],startY: 0,moveY: 0,moving: false}},watch: {urls: {handler(val) {this.images = val.map(url => ({url,scale: 1,loaded: false}))},immediate: true}},methods: {handleChange(e) {this.$emit('update:current', e.detail.current)},imageLoaded(index) {this.$set(this.images[index], 'loaded', true)},handleScale(e, index) {this.$set(this.images[index], 'scale', e.detail.scale)},handleMoveChange() {// 處理圖片拖動事件},handleTouchStart(e) {this.startY = e.touches[0].clientY},handleTouchMove(e) {if (this.images[this.current].scale > 1) returnthis.moveY = e.touches[0].clientY - this.startYif (this.moveY > 0) {this.moving = true}},handleTouchEnd() {if (this.moving && this.moveY > 100) {this.close()}this.moving = falsethis.moveY = 0},close() {this.$emit('close')},saveImage() {const url = this.images[this.current].url// 先下載圖片到本地uni.downloadFile({url,success: (res) => {// 保存圖片到相冊uni.saveImageToPhotosAlbum({filePath: res.tempFilePath,success: () => {uni.showToast({title: '保存成功',icon: 'success'})},fail: () => {uni.showToast({title: '保存失敗',icon: 'none'})}})}})}}
}
</script><style>
.image-previewer {position: fixed;top: 0;left: 0;right: 0;bottom: 0;background-color: #000;z-index: 999;display: flex;flex-direction: column;
}.previewer-header {height: 88rpx;display: flex;align-items: center;justify-content: space-between;padding: 0 30rpx;
}.counter {color: #fff;font-size: 28rpx;
}.close {color: #fff;font-size: 60rpx;line-height: 1;
}.swiper {flex: 1;width: 100%;
}.movable-area {width: 100%;height: 100%;
}.movable-view {width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;
}.movable-view image {width: 100%;
}.previewer-footer {height: 100rpx;display: flex;align-items: center;justify-content: center;
}.save-btn {color: #fff;font-size: 28rpx;padding: 10rpx 30rpx;border-radius: 30rpx;background-color: rgba(255, 255, 255, 0.2);
}
</style>

這個組件實現了以下功能:

  • 圖片切換(使用swiper組件)
  • 圖片縮放(movable-view的scale屬性)
  • 向下滑動關閉預覽
  • 保存圖片到本地相冊

3. 添加圖片相冊功能

為了增強應用的實用性,我們來添加一個相冊分類功能:

<template><view class="album"><view class="tabs"><view class="tab-item" v-for="(item, index) in albums" :key="index":class="{ active: currentAlbum === index }"@tap="switchAlbum(index)"><text>{{ item.name }}</text></view></view><view class="content"><view class="album-info"><text class="album-name">{{ albums[currentAlbum].name }}</text><text class="album-count">{{ imageList.length }}張照片</text></view><view class="image-grid"><view class="image-item" v-for="(item, index) in imageList" :key="index"@tap="previewImage(index)"><image :src="item.thumb || item.url" mode="aspectFill"lazy-load></image></view></view></view></view>
</template><script>
export default {data() {return {albums: [{ id: 1, name: '風景' },{ id: 2, name: '人物' },{ id: 3, name: '動物' },{ id: 4, name: '植物' }],currentAlbum: 0,imageList: []}},onLoad() {this.loadAlbumImages()},methods: {switchAlbum(index) {if (this.currentAlbum === index) returnthis.currentAlbum = indexthis.loadAlbumImages()},loadAlbumImages() {const albumId = this.albums[this.currentAlbum].id// 模擬加載不同相冊的圖片uni.showLoading({ title: '加載中' })setTimeout(() => {// 模擬API返回數據this.imageList = Array(15).fill(0).map((_, i) => ({id: i + 1,url: `https://picsum.photos/seed/${albumId * 100 + i}/500/500`,thumb: `https://picsum.photos/seed/${albumId * 100 + i}/200/200`}))uni.hideLoading()}, 800)},previewImage(index) {const urls = this.imageList.map(item => item.url)uni.previewImage({urls,current: urls[index]})}}
}
</script><style>
.album {display: flex;flex-direction: column;height: 100vh;
}.tabs {display: flex;height: 80rpx;border-bottom: 1rpx solid #eee;
}.tab-item {flex: 1;display: flex;align-items: center;justify-content: center;position: relative;
}.tab-item.active {color: #007AFF;
}.tab-item.active::after {content: '';position: absolute;bottom: 0;left: 25%;width: 50%;height: 4rpx;background-color: #007AFF;
}.content {flex: 1;padding: 20rpx;
}.album-info {margin-bottom: 20rpx;
}.album-name {font-size: 36rpx;font-weight: bold;
}.album-count {font-size: 24rpx;color: #999;margin-left: 20rpx;
}.image-grid {display: flex;flex-wrap: wrap;
}.image-item {width: 33.33%;padding: 5rpx;box-sizing: border-box;
}.image-item image {width: 100%;height: 220rpx;border-radius: 8rpx;
}
</style>

性能優化

開發過程中,我注意到一些性能問題,特別是圖片加載較慢的情況,因此做了以下優化:

  1. 懶加載:使用lazy-load屬性延遲加載圖片
  2. 縮略圖預加載:先加載小圖,再加載大圖
  3. 圖片壓縮:在上傳和展示時進行適當壓縮
// 圖片壓縮工具函數
export function compressImage(src, quality = 80) {return new Promise((resolve, reject) => {uni.compressImage({src,quality,success: res => {resolve(res.tempFilePath)},fail: err => {reject(err)}})})
}
  1. 虛擬列表:當圖片數量很多時,考慮使用虛擬列表技術

踩坑記錄

開發過程中遇到了一些坑,在此記錄,希望能幫助到大家:

  1. 兼容性問題:H5和App表現一致,但在小程序中movable-view的縮放效果不太理想,需要針對不同平臺做兼容處理
  2. 圖片預覽:小程序的圖片預覽API不支持長按保存,需要自己實現
  3. 內存問題:加載大量高清圖片容易導致內存占用過高,需要做好圖片資源管理

總結

通過這個項目,我實現了一個簡單但功能完善的圖片瀏覽器。UniApp的跨平臺能力確實令人印象深刻,一套代碼能夠同時運行在多個平臺上,大大提高了開發效率。

當然,這個應用還有很多可以改進的地方,比如添加圖片濾鏡、優化動畫效果、增加云存儲功能等。希望這篇文章對你有所幫助,有任何問題歡迎在評論區留言討論!

參考資料

  1. UniApp官方文檔
  2. Vue.js指南

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83761.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83761.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83761.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python爬蟲實戰:獲取taobao網最新rtx5060ti顯卡銷量數據并分析,為消費者做參考

一、系統定義與技術架構 1.1 系統定義 本系統是基于 Python 開發的電商數據采集與分析工具,旨在通過模擬用戶行為實現淘寶平臺 50 系列顯卡(以 RTX 5060 Ti 為例)銷售數據的自動化獲取、清洗、分析及可視化。核心功能包括: 自動登錄:通過 Selenium 模擬瀏覽器操作完成賬…

OCframework編譯Swift

建一個OC的framework&#xff1a; 需要對外暴露的OC文件&#xff0c;需要放到OC的.h文件中 framework中&#xff0c;OC類&#xff0c;調用framework中的Swift類&#xff1a; #import "WowAudioFocus/WowAudioFocus-Swift.h" //02 #import "{工程名}/{工程…

每日算法 -【Swift 算法】Two Sum 問題:從暴力解法到最優解法的演進

【Swift 算法】Two Sum 問題&#xff1a;從暴力解法到最優解法的演進 本文通過“Two Sum”問題&#xff0c;帶你了解如何從最直觀的暴力解法&#xff0c;逐步優化到高效的哈希表解法&#xff0c;并對兩者進行對比&#xff0c;適合算法入門和面試準備。 &#x1f4a1; 問題描述 …

【保姆級】Nginx簡介以及安裝

Nginx簡介 ? Nginx是一個高性能的HTTP和反向代理web服務器&#xff0c;同時也提供了IMAP/POP3/SMTP服務。Nginx是由伊戈爾賽索耶夫為俄羅斯訪問量第二的Rambler.ru站點&#xff08;俄文&#xff1a;Рамблер&#xff09;開發的&#xff0c;第一個公開版本0.1.0發布于20…

C++(25): 標準庫 <deque>

目錄 1、 核心概念 2. 基本語法 3. 特點 4. 特有成員函數 5. 內存與性能 6. 示例代碼 7. 成員函數列表 8. 使用場景 9. 注意事項 1、 核心概念 雙端隊列(Double-Ended Queue,deque) 是一種允許在隊列頭部和尾部高效插入和刪除元素的線性數據結構,同時支持隨機訪問。…

軟件設計師關系代數和元組演算(關聯、笛卡爾積、除、映射、分段等問題)考點分析——求三連

一、考點分值占比與趨勢分析 綜合知識歷年統計表 年份考題數量分值分值占比考察重點2018334%自然連接、投影、選擇2019222.67%笛卡爾積、條件篩選2020111.33%屬性列計算2021334%關系運算綜合應用2022222.67%元組演算表達式2023222.67%差運算、連接類型2024111.33%除法運算應用…

卸載云樞(MacOS 版)

刪除 APP 和相關文件 sudo chflags -R noschg /Applications/Yunshu.app 2>/dev/null sudo rm -rf /Applications/Yunshu.app sudo rm -rf /Library/Application\ Support/EagleCloud sudo rm -rf /Library/LaunchAgents/com.eagleyun.endpoint.agent.plist sudo rm -rf /L…

在 Ubuntu 20.04 中使用 init.d 或者systemd實現開機自動執行腳本

Ubuntu 20 默認使用的是 systemd 系統管理器&#xff0c;但傳統的 SysV Init&#xff08;/etc/init.d/&#xff09;腳本依然兼容并可用。本文將介紹如何通過 init.d 寫腳本來在開機時自動設置某個 GPIO&#xff08;如 GPIO407&#xff09;為高電平&#xff0c;適用于嵌入式系統…

蘋果的人工智能領域慢熱

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

FastAPI使用@app.get/@app.post等裝飾器注冊路由無效404 Not Found

&#xff08;一&#xff09;問題描述 使用app.get注冊路由&#xff0c;前端發送請求訪問路徑和路由一致&#xff0c;但一直顯示404 Not Found&#xff0c;檢查了好幾遍&#xff0c;確認沒有訪問路徑不一致的問題。 在Swagger文檔里查看&#xff0c;也沒有找到這個新添加的接口。…

制作我的計算器

1. 界面布局 新建項目 MyCalculator&#xff0c;開始布局。 2. 靜態布局 代碼如下&#xff1a; // etc/pages/Index.ets Entry Component struct Index {build() {Column() {/*** 運算區*/Column() {TextInput({ text: 12x13 }).height(100%).fontSize(32).enabled(false).f…

2025-5-17Vue3快速上手

1、ref對比reactive 區別第2點&#xff1a;本質是指針指向問題 整體修改reactive的數據時&#xff0c;有坑 使用原則需要根據項目原本的代碼靈活參考 如果要更新的數據是從服務器獲取回來的&#xff0c;用Object.assign是好方法&#xff0c;需要注意的是&#xff1a;Object.a…

深度學習---模型預熱(Model Warm-Up)

一、基本概念與核心定義 模型預熱是指在機器學習模型正式訓練或推理前&#xff0c;通過特定技術手段使模型參數、計算圖或運行環境提前進入穩定狀態的過程。其本質是通過預處理操作降低初始階段的不穩定性&#xff0c;從而提升后續任務的效率、精度或性能。 核心目標&#xf…

加載渲染geojson數據

本節我們學習如何在cesium中加載geojson數據 想要加載geojson數據首先要有數據源,我們以中國地圖為例 復制數據的geo api 在cesium的官網庫中查詢 可以看到如何在cesium中導入數據的方法 //加載geojson數據let dataGeo Cesium.GeoJsonDataSource.load("https://geo.dat…

python:pymysql概念、基本操作和注入問題講解

python&#xff1a;pymysql分享目錄 一、概念二、數據準備三、安裝pymysql四、pymysql使用&#xff08;一&#xff09;使用步驟&#xff08;二&#xff09;查詢操作&#xff08;三&#xff09;增&#xff08;四&#xff09;改&#xff08;五&#xff09;刪 五、關于pymysql注入…

職坐標AIoT技能培訓課程實戰解析

職坐標AIoT技能培訓課程以人工智能與物聯網技術深度融合為核心&#xff0c;構建了“理論實戰行業應用”三位一體的教學體系。課程體系覆蓋Python編程基礎、傳感器數據采集、邊緣計算開發、云端服務部署及智能硬件開發全鏈路&#xff0c;通過分層遞進的知識模塊幫助學員建立系統…

MySQL 用戶權限管理:從入門到精通

在當今數據驅動的時代&#xff0c;數據庫安全已成為企業信息安全體系的核心組成部分。作為最流行的開源關系型數據庫之一&#xff0c;MySQL 的用戶權限管理系統提供了強大而靈活的訪問控制機制。本文將全面解析 MySQL 用戶權限管理的各個方面&#xff0c;幫助數據庫管理員和開發…

Java常見API文檔(下)

格式化的時間形式的常用模式對應關系如下&#xff1a; 空參構造創造simdateformate對象&#xff0c;默認格式 練習.按照指定格式展示 package kl002;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class Date3 {publi…

博圖1200硬件組態與啟保停程序編寫步驟詳解

一、前言 在工業自動化控制領域&#xff0c;西門子S7-1200 PLC因其性能穩定、編程靈活而廣受歡迎。本文將詳細介紹使用TIA Portal&#xff08;博圖&#xff09;軟件進行S7-1200 PLC硬件組態以及編寫基本啟保停程序的完整步驟&#xff0c;幫助初學者快速掌握這一基礎而重要的技…

AutoMouser - 單次AI調用鑄就高效自動化腳本

你是否厭倦了反復點點點的枯燥操作&#xff1f;是否希望像科幻電影那樣&#xff0c;一句指令&#xff0c;萬事搞定&#xff1f;如果告訴你&#xff0c;現在只需要一次AI調用&#xff0c;就能自動執行一整套鼠標腳本操作&#xff0c;你會不會覺得&#xff1a;自動化的時代&#…