做前端的同学,如果接到一个“手绘地图导览”的需求,第一反应往往是头皮发麻。传统的 WebGIS 方案(如高德、百度地图)都是基于 WGS84 或 GCJ02 等地理坐标系,而手绘地图通常只是一张精美的 JPG/PNG 原图,没有经纬度概念,怎么把 POI 准确地点上去?怎么做缩放?怎么做全景联动?

FunMapUI 是我自研的一个手绘地图导览项目,基于 Vue 3 + Vite + Leaflet 构建,后端则使用了我自己开发的 PHP 框架 restina-framework。它给出了一套非常优雅且轻量的解法,完美解决了手绘地图的像素级渲染与交互问题。今天就来给大家拆解一下这个项目的技术亮点与架构设计,希望能给正在做类似需求的同学一些启发。
技术选型:轻量与高效的完美结合
FunMapUI 的技术栈非常现代化,主打一个“开箱即用”:
– 核心框架:Vue 3 + Vite,构建速度极快,开发体验拉满。
– 地图引擎:Leaflet。相比 Mapbox 或 OpenLayers,Leaflet 体积更小,且对自定义坐标系(CRS)的支持非常友好,特别适合手绘地图场景。
– 状态管理:Pinia。完美契合 Vue 3 的 Composition API,逻辑更清晰。
– UI 组件库:Vant。移动端组件丰富,配合 unplugin-vue-components 实现按需自动导入,彻底告别繁琐的 import 样板代码。
– 全景查看:@photo-sphere-viewer/core,轻松实现 360° 沉浸式全景。
– 后端框架:restina-framework。这是我自研的 PHP 框架,轻量高效,专为 RESTful API 设计,与前端 Vue 3 配合默契,前后端分离架构清晰明了。
核心架构:如何搞定像素坐标系?
这是整个项目最核心的技术点。传统地图用经纬度,而手绘地图我们用像素。
在 useMap.js 这个组合式函数中,我使用了 Leaflet 的 CRS.Simple(简单像素坐标系)。核心逻辑是:
1. 计算缩放比例:通过 scale = 256 / paddedDim,确保瓦片尺寸与像素坐标严格一致。
2. 覆盖投影边界:将 bounds 强制设置为 [0,0] 到 [paddedDim, paddedDim],彻底剥离经纬度语义。
3. 瓦片 Y 轴翻转:手绘地图瓦片的存储约定往往和标准地图相反,通过自定义 getTileUrl 对 y 坐标进行翻转,完美解决瓦片加载错乱问题。
4. 丝滑的无级缩放:开启 zoomSnap: 0,并禁用了 Leaflet 内置的 touchZoom,改用自定义的双指手势,超过阈值才触发整级缩放,体验极其丝滑。
状态管理与组件编排
项目的状态划分非常清晰,主要分为两个 Store:
– map store:负责“地图基建”,包括图片尺寸、bounds、中心点、缩放范围以及像素与百分比坐标的互转。
– poi store:负责“业务数据”,维护 POI 列表、分类过滤、搜索状态以及当前选中项。
在视图层,HomeView.vue 作为总调度,将 editMode 和事件下发给 LeafletMap.vue。地图组件内部通过监听 poiStore.filteredPois 的变化,动态增删 Marker。更有趣的是,它还利用 Canvas 的 measureText 方法来测量文字宽度,实现了标记容器大小的自适应,细节拉满。
性能优化思路:移动端地图的必修课
在移动端跑地图,性能是重中之重。FunMapUI 在这方面做了很多考量:
1. 内存管理:地图销毁时严格调用 map.remove();在更新 POI 前会先移除旧 Marker;编辑模式切换时及时解绑事件,防止内存泄漏。
2. 渲染优化:使用 computed 派生过滤后的 POI 数据,避免重复计算;复用 Canvas 实例测量文本宽度。
3. 资源优化:建议将瓦片转为 WebP/AVIF 格式以减小体积;对大图进行分块与延迟加载;路由和大型组件均采用懒加载,降低首屏包体。
4. 网络加速:瓦片与静态资源开启强缓存,配合 HTTP/2 与 CDN,让地图滑动如丝般顺滑。
开发体验与调试避坑
得益于 Vite 的配置,启动项目只需 npm run dev,并且默认开启了 0.0.0.0,局域网内手机扫码就能直接真机调试,非常方便。
当然,开发过程中也有一些常见的坑需要避开:
– 瓦片不显示:第一时间检查 tilesPath 路径配置和 Y 轴翻转逻辑。
– 标记位置偏移:核对百分比坐标与像素坐标的转换公式。
– 触摸缩放不灵敏:可以调整 PINCH_THRESHOLD 或 zoomDelta 参数。
总结
FunMapUI 是我自研的一个手绘地图导览项目,不仅解决了像素级地图渲染的核心难题,还配套了自研的 restina-framework PHP 后端框架提供 API 支持。从自定义 CRS、瓦片翻转,到状态管理、性能优化,整个项目代码结构清晰,注释详尽。如果你正在为手绘地图导览、景区地图、室内导航等场景发愁,欢迎 star 一下这个项目,也期待与大家一起交流探讨。

