博客 / 詳情

返回

uni-app使用瓦片實現離線地圖的兩種方案

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

最近接到一個安卓App的活兒,雖然功能上不算複雜,但因為原本沒怎麼做過安卓端,所以也是"摸着石頭過河"。簡單寫一下踩過的坑和淌的水吧~

uni-app實現離線地圖主要用 leafletjs 實現,但是因為在安卓端運行,存在渲染問題,所以還要用上 renderjs

實現方案一:web-view

因為uni-app引入第三方可以採用傳統的 NPM 安裝的方式,也可以採用引入打包完的js文件的方式。

這裏採用 leafletjs 打包完的文件,將 leafletjs 放入 static 文件夾內。

在網上下載了公開的瓦片地圖圖片,以 {z}/{x}/{y} 的目錄結構放入 tiles 文件夾中,將 tiles 放入 static 文件夾內。

在static文件夾下新建一個 offline-map.html 文件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>離線地圖</title>
		<link rel="stylesheet" href="./leaflet/leaflet.css" />
		<style>
			html,
			body {
				margin: 0;
				padding: 0;
			}

			#map {
				height: 100vh;
				width: 100vw;
				margin: 0;
				padding: 0;
			}
		</style>
	</head>
	<body>
		<div id="map"></div>
		<script src="./leaflet/leaflet.js"></script>
		<script>
			const baseUrl = './tiles/{z}/{x}/{y}.jpg';
			const map = L.map('map').setView([23.56, 113.23], 15);

			L.tileLayer(baseUrl, {
				minZoom: 15,
				maxZoom: 18,
				tms: true,
				attribution: 'Offline Tiles',
				errorTileUrl: ''
			}).addTo(map);
		</script>
	</body>
</html>

找到 pages/index/index.vue 文件,採用 web-view 引用的方式引入上述 html 文件。

// pages/index/index.vue
<template>
	<view class="content">
		<web-view src="/static/offline-map.html"></web-view>
	</view>
</template>

<style>
	.content {
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}
</style>

實現方案二:renderjs

仍然將 leafletjs 和 瓦片圖片文件夾tiles 放入 static 文件夾中。

// pages/index/index.vue
<view class="content">
    <view id="map" class="map-container"></view>
</view>

<script module="leaflet" lang="renderjs">
    import '@/static/leaflet/leaflet.css';
	import * as L from "@/static/leaflet/leaflet.js";

    export default {
		mounted() {
			this.initMap();
		},
		methods: {
			initMap() {
				const baseUrl = 'static/tiles/{z}/{x}/{y}.jpg'
				map = L.map('map').setView([23.56, 113.23], 15);

				L.tileLayer(baseUrl, {
					minZoom: 15,
					maxZoom: 18,
					tms: true,
					attribution: 'Offline Tiles',
					errorTileUrl: ''
				}).addTo(map);
			},
        }
    }
</script>

這裏需要注意的是一定要在 renderjs 中實現上述代碼,如果在常規 script 中實現,在 H5端 沒有任何問題,但是運行到真機上會白屏。(這個問題我反覆試了好幾次都不行,結果還是上傳到 Trae 上解決了這個問題)。

導致這種情況的原因是在常規 sctipt 中的代碼,在真機上是運行在 邏輯層 的代碼,無法干擾到 視圖層 的結構,這一點和Web是不同的。

而 renderjs 是運行在 視圖層 的js,具備操作 DOM 的能力。

其次是引用 static 文件的路徑,import static 中的文件可以使用 @/static 的方式,但是在代碼中引用 static 文件需要採用 static/ 的形式。

總結

最後我做完以後讓 Trae 給了一下評價,Trae 表示不建議採用這種方式實現離線地圖,首先瓦片地圖文件一般非常大,我用的僅僅是其中的一小部分,也超過了 60MB,打包出來的 App 包太大了。

其次無論是 web-view 還是 renderjs 本質上是一樣的。在app-vue環境下,視圖層由webview渲染,而renderjs就是運行在視圖層的。

所以無論是渲染效率還是開發上基本沒差。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.