5.3 浏览器端与移动端开发


5.3 浏览器端与移动端开发

本节摘要:5.2 把服务发了出去,本节站在消费端把服务用起来——用 JavaScript 在网页里加载服务、查询要素、渲染结果,再看移动端在线与离线两种活法。这是全册第一次把代码跑在"读者"那一侧,也是第 6 章二次开发的热身场。

一个网页地图的最小骨架

先跑通再谈优化。一个能加载 IGServer 服务的网页,结构上只需要三块:一个装地图的容器、一段创建地图对象的脚本、一个指向服务的图层。MapGIS 的 Web 客户端开发包基于开放图层体系封装,会其中一个,另一个的代码读起来也不陌生。

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>耕地保护浏览页</title> <!-- 引入开发包样式与脚本 本地部署或平台分发均可 --> <style> #map { width: 100%; height: 560px; } </style> </head> <body> <div id="map"></div> <script> // 第一步 创建地图对象 绑定容器 var map = new ol.Map({ target: 'map', // 第二步 挂载瓦片图层 指向 5.2 发布的服务 layers: [ new ol.layer.Tile({ source: new ol.source.TileIGS({ url: 'http://服务器地址:6163/igs/rest/mrms/tile/farmland_protect' }) }) ], // 第三步 定初始视图 中心与层级 view: new ol.View({ center: [113.8, 34.2], // 项目县的大致中心 zoom: 11, projection: 'EPSG:4326' // 与服务支持的坐标系一致 }) }); // 打开浏览器控制台 无报错且出图 即骨架通了 </script> </body> </html>

骨架通了之后,最常加的下一块积木是"点一下查属性"。交互的关键是把屏幕点击翻译成坐标,再把坐标连同范围条件发给要素服务:

// 点击查询:屏幕坐标 转地图坐标 发查询 解析返回 渲染高亮 map.on('singleclick', function (evt) { var coordinate = evt.coordinate; // 地图坐标 var query = new Zondy.Service.QueryLayerFeature({ layer: 'farmland_protect/0', // 服务名加图层序号 ip: '服务器地址', port: '6163' }); query.queryParam = new Zondy.Service.QueryParameter({ geometry: new Zondy.Object.Point(coordinate[0], coordinate[1]), radius: 0.001, // 点击容差 换算成坐标单位 resultFormat: 'json' }); query.query(function (result) { // 发起请求 if (!result.TotalCount) { return; } // 没点中要素 var f = result.SFEleArray[0]; // 取第一个命中要素 showPanel(f.FldName, f.FldValue); // 字段名与字段值成对展示 }, function (err) { console.log('查询失败', err); }); }); // 输出:点击图斑 弹出面板显示 地类编码 面积 权属单位

这段代码里值得抠的细节是 radius 容差。手指与鼠标都不可能精确到像素级,给一个小半径把"点"变成"小圆"更符合人的操作习惯;容差给太大又会一击命中多个要素,弹窗内容变得不确定。移动端建议容差略大于桌面端——手指比鼠标指针粗得多。

学习目标

阅读完本节,你应当能够:

  1. 独立写出加载 IGServer 服务的最小网页并跑通
  2. 实现点击查询要素并把属性渲染到面板
  3. 画出一次浏览器与服务端的请求时序,指出每步的耗时来源
  4. 为移动场景在"在线服务"与"离线包"之间做选择并说明同步策略
  5. 描述移动端开发与桌面网页开发在交互、性能上的三大差异

一次请求的时序:网页地图为什么"顿"

把浏览器里一次地图加载画成时序,性能问题就有了着落处:

时序里藏着两类"顿"。首次加载顿:控制台里几十个请求同时发出,服务器并发能力决定首屏时间——这正是 5.2 缓存预生成的用武之地。交互顿:瓦片早就在本地缓存了,但浏览器主线程被别的脚本占着,图就在那"卡一下才动"。第二类问题与服务端无关,前端要做的功课是少在主线程做重计算、图层分级加载(先底图后专题)、大数据量的图层改用聚合显示而不是一次画几千个点。

💡 关键直觉:网页地图性能优化的顺序是——先确认瓦片命中缓存(服务端),再查请求数量与并发(网络),最后才动前端渲染逻辑。顺序反了容易白忙。

移动端:在线与离线是两种活法

移动 GIS 的开发包把地图控件、数据访问、定位能力打包进了手机。与网页开发比,三件事变了:交互从鼠标变成手指,按钮要够大、容差要放宽;性能预算更紧,手机内存与电量都经不起几千要素的实时渲染;网络不再可靠,山区、井下、断网巡查是常态而不是异常。

网络的不可靠把移动端劈成两种活法:

# 在线模式与离线模式选型 维度 在线服务模式 离线包模式 数据位置 服务端 现场请求 本地 已下载 实时性 最新 更新周期到下次同步 弱网表现 白屏 降级 不受影响 存储占用 几乎为零 数百兆到数个G 适用 办公网内巡查 查询为主 外业调绘 无人区 应急 # 离线模式的三段式生命期: # 1 出发前 在线下载任务包 边界 范围 层级 专题数据一并打包 # 2 外业中 全离线操作 采集与修改写入本地库 # 3 归队后 同步回传 按要素版本合并 冲突人工裁决

移动端代码的骨架与网页惊人地像——同样是"容器、地图对象、图层"三板斧,只是生命周期管理必须更严格,地图控件要跟着界面暂停与销毁:

// Android 端加载服务的骨架(示意) public class MapActivity extends AppCompatActivity { private MapView mapView; @Override protected void onCreate(Bundle b) { super.onCreate(b); setContentView(R.layout.activity_map); mapView = findViewById(R.id.mapView); mapView.getMap().loadIGSService( "http://服务器地址:6163/igs/rest/mrms/docs/farmland_protect"); } @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override protected void onPause() { super.onPause(); mapView.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); } // 三个生命周期回调一个都不能省 走漏一个 轻则黑屏重则内存泄漏 }

⚠️ 常见坑:离线包同步冲突没有设计裁决规则。两个外业队员在重叠区域各改了同一块图斑,归队同步时程序不知听谁的,要么覆盖丢数据,要么报错卡流程。同步设计必须带版本与冲突处理策略——字段级合并、以新为准或人工裁决,三选一,都要在项目初期定好。

这一节的收束与下一章的接力

本节跑通了消费端:网页加载、点击查询、移动离线。但到此为止我们写的都是"用服务"的代码,还没碰"改产线"的代码——把分析算法挂到服务端、把重复操作做成插件、用脚本把批处理自动化,那是下一章二次开发的领地。本节的时序图与容差、生命周期这些细节,到那边会以更完整的工程形态重现。

  • 最小骨架:容器、地图对象、图层三件套,先跑通再优化
  • 点击查询:屏幕坐标转地图坐标、容差把点变圆、字段成对渲染
  • 两类卡顿:首屏看缓存命中,交互看主线程占用,优化顺序别颠倒
  • 移动三板斧:交互放大、性能从紧、网络不可靠当常态设计
  • 离线三段式:出发打包、外业离线、归队同步,冲突规则先定后用
  • 生命周期:移动端地图控件的暂停与销毁回调一个不能漏

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U