高德地图+LBS思想实现基于组合需求的路径规划——以钓鱼点POI为例
本文介绍了一个基于高德地图API开发的钓鱼指南平台,采用前后端分离架构(HTML/CSS/JS前端+JavaServlet后端+PostgreSQL数据库),通过LBS位置服务思想实现钓鱼点智能推荐与路径规划。平台核心功能包括:1)可视化展示用户上传的钓鱼点信息;2)支持按鱼类组合筛选目的地;3)自动计算最近钓鱼点并规划导航路线。系统利用高德API实现地图展示、标记添加和路径规划,通过空间数据存储
前言
日常生活中,常常面临在多个相似目的地之间选择,往往真正缺乏的不是路径规划,而是对“哪个更符合需求”+“哪个最近”的清晰认识。解决这一问题其实并不需要详细了解每个目的地的具体距离,而只需将这些同类POI和起点坐标标记在地图上,便能直观地识别出哪个离我们最近。结合高德地图与LBS(位置服务)思想,本文将以钓鱼平台为例,探讨如何基于组合需求,实现对目的地的有效路径规划,帮助用户快速做出决策。
背景
作为钓鱼爱好者,一直希望有一个平台能帮用户找到合适的钓鱼地点、记录和分享钓鱼成果。此外,如何找到一个“最近”的鱼塘“既能钓鲫鱼又能钓鲢鱼”这样的需求便成为了本项目的初衷。
技术架构
平台采用前后端分离的架构,主要组成部分如下:
前端:使用HTML、CSS和JS构建用户界面,并通过高德地图API展示地图和钓鱼点信息。
后端:基于Java Servlet技术,处理用户请求,连接PostgreSQL数据库。
数据库:使用PostgreSQL便于储存空间数据点,管理用户上传的钓鱼信息和记录。
方案设计
输入:
用户通过前端界面上传钓鱼信息,包括鱼类名称、钓鱼地点及时间。
这些信息被发送到后端,通过相应的Servlet处理,并存储到数据库中。
输出:
用户请求时,后端从数据库中检索钓鱼点信息,并将结果返回前端。
例如,通过GetFishInfoServlet.java,系统获取并返回钓鱼记录数据,供用户在地图上查看。
|
<pre class="ag" style="font-family:monospace;">try (Connection connection = Database.getConnection()) { String sql = "SELECT l.location_id, f.fish_name, l.latitude, l.longitude, l.province, l.city, l.district " + "FROM locations l " + "JOIN fishing_records fr ON l.location_id = fr.location_id " + "JOIN fish f ON fr.fish_id = f.fish_id"; Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int locationId = rs.getInt("location_id"); String fishName = rs.getString("fish_name"); double latitude = rs.getDouble("latitude"); double longitude = rs.getDouble("longitude"); String province = rs.getString("province"); String city = rs.getString("city"); String district = rs.getString("district"); FishInfo fishInfo = new FishInfo(locationId, fishName, latitude, longitude, province, city, district); fishList.add(fishInfo); } rs.close(); stmt.close(); } catch (SQLException e) { e.printStackTrace(); } </pre> |
高德API的使用
在钓鱼指南平台中,高德地图API主要用于:
1.地图初始化与设置
|
var map; var driving; var Center = localStorage.getItem('mapCenter') ? JSON.parse(localStorage.getItem('mapCenter')) : [114.361084, 30.533393]; var Zoom = localStorage.getItem('mapZoom') ? parseInt(localStorage.getItem('mapZoom')) : 12; function initMap() { map = new AMap.Map('mapContainer', { zoom: Zoom, center: Center, mapStyle: 'amap://styles/fresh' }); driving = new AMap.Driving({ map: map, panel: "panel" }); // 地图点击事件,用于标记钓鱼点 map.on('click', function (e) { var lat = e.lnglat.getLat(); var lng = e.lnglat.getLng(); document.getElementById('latitude').value = lat; document.getElementById('longitude').value = lng; if (marker) { marker.setMap(null); } marker = new AMap.Marker({ position: [lng, lat], map: map, icon: blueIcon, offset: new AMap.Pixel(-21, -43) }); }); } |
在这段代码中,首先声明了 map 和 driving 变量,分别用于存储地图实例和路径规划实例。通过 localStorage 获取地图的初始中心和缩放级别,如果没有保存的状态则使用默认值。initMap 函数负责创建地图实例,并设置缩放、中心位置和样式。
添加地图的点击事件以便用户可以在地图上选择位置。当用户点击地图时,事件处理程序会获取点击位置的经纬度,并在该位置放置一个标记。这样用户可以直观地看到自己选择的位置。
2.添加钓鱼点标记
|
function addMarker(lat, lng, fishInfo) { var marker = new AMap.Marker({ position: [lng, lat], map: map, icon: redIcon, offset: new AMap.Pixel(-17, -25) }); marker.content = fishInfo; marker.on('click', function (e) { infoWindow = new AMap.InfoWindow({ content: e.target.content, offset: new AMap.Pixel(0, -30) }); infoWindow.open(map, e.target.getPosition()); }); } |
addMarker 函数用于在地图上添加钓鱼点的标记。通过传入纬度、经度和钓鱼点信息,该函数创建一个新的标记,并设置其位置和图标。标记上还附加了钓鱼点的信息内容,以便在用户点击标记时能够显示详细信息。
点击标记时,事件处理程序会创建一个信息窗口并显示相关内容,让用户能够快速获取该钓鱼点的详细信息。这种设计使得用户能够与地图进行互动,获取更丰富的上下文信息。
3.页面加载时获取钓鱼点信息
|
window.onload = function () { initMap(); // 从服务器获取钓鱼点信息并添加到地图 fetch('GetFishInfoServlet') .then(response => response.json()) .then(data => { data.forEach(fish => { var con = "<div>"+ "<h3>"+fish.fishName+"</h3>"+ "<p>省份:"+fish.province+"</p>"+ "<p>城市: "+fish.city+"</p>"+ "<p>区县: "+fish.district+"</p>"+ "<p>纬度: "+fish.latitude+"</p>"+ "<p>经度: "+fish.longitude+"</p>"+ "</div>" ; addMarker(fish.latitude, fish.longitude, con); }); }) .catch(error => console.error('Error:', error)); } |
在页面加载时,window.onload 函数首先调用 initMap 来初始化地图。接下来,通过 fetch 请求 GetFishInfoServlet 接口从服务器获取钓鱼点的信息。获取的数据会以JSON格式返回,然后通过遍历这些数据,使用 addMarker 函数将每个钓鱼点在地图上标记出来。
每个钓鱼点的信息被构建为一个HTML片段,包含鱼类名称、所在省份、城市、区县以及其经纬度等。这种方式让用户在地图上能够快速识别钓鱼点及其相关信息,提升了用户体验。
4. 清除标记与存储处理
|
function clearMarkers() { map.clearMap(); } function clearLocalStorage() { localStorage.removeItem('mapCenter'); localStorage.removeItem('mapZoom'); alert('本地存储已清除。地图将在下次加载时重置为默认位置。'); } |
clearMarkers 函数用于清除地图上的所有标记,使地图恢复到初始状态。这在用户需要重新选择位置或查看不同钓鱼点时非常有用。
clearLocalStorage 函数则用于清除本地存储中的地图状态,使得下次加载时地图能够重置为默认位置。同时会弹出提示,告知用户本地存储已被清除,增强了用户的操作反馈。
5.路径规划
当然,还有最重要的路径规划部分。
首先初始化路径规划实例:
|
driving = new AMap.Driving({ map: map, panel: "panel" }); |
在 initMap 函数中,driving 变量被初始化为一个高德地图的驾车路径规划实例。此实例通过将其与地图实例 (map) 和用于展示导航信息的面板 (panel) 关联,实现路径规划功能。这意味着用户可以通过该实例请求从起点到终点的导航。
|
function startNavigation() { var fishName = document.getElementById('search_fish_name').value; var lat = document.getElementById('latitude').value; var lng = document.getElementById('longitude').value; if (!fishName || !lat || !lng) { alert('请点击地图以选择坐标并输入鱼名'); return; } fetch('SearchFishInfoServlet?search_fish_name=' + fishName + '&latitude=' + lat + '&longitude=' + lng + "&kind=" + 1) .then(response => response.json()) .then(data => { clearMarkers(); var marker = new AMap.Marker({ position: [lng, lat], map: map, icon: blueIcon, offset: new AMap.Pixel(-21, -43) }); data.forEach(fish => { addMarker(fish.latitude, fish.longitude, fish); driving.search(new AMap.LngLat(lng, lat), new AMap.LngLat(fish.longitude, fish.latitude), function (status, result) { if (status === 'complete') { console.log('路线绘制完成'); } else { console.error('获取驾车数据失败:', result); } }); }); }) .catch(error => console.error('Error:', error)); } |
定义开始导航功能,在 startNavigation 函数中,用户输入的鱼类名称、纬度和经度会被提取。如果这些信息不完整,系统会提醒用户进行必要的输入。接下来,程序向 SearchFishInfoServlet 发送请求,查找与该鱼类相关的钓鱼点。
一旦获取到相关钓鱼点的信息,程序会首先清除之前的标记,然后在用户选定的位置添加一个标记。在获取的钓鱼点数据中,调用 driving.search 方法进行路径规划。
|
driving.search(new AMap.LngLat(lng, lat), new AMap.LngLat(fish.longitude, fish.latitude), function (status, result) { if (status === 'complete') { console.log('路线绘制完成'); } else { console.error('获取驾车数据失败:', result); } }); |
driving.search 方法接收起始点(用户当前位置)和目标点(钓鱼点)的经纬度,并在回调函数中处理结果。如果路径规划成功,控制台将显示“路线绘制完成”;如果失败,则输出错误信息。这一过程实现了用户从当前位置到钓鱼点的导航功能。
|
function stopNavigation() { driving.clear(); // Clear the navigation console.log('导航已停止'); } |
stopNavigation 函数用于停止当前的导航操作,通过调用 driving.clear() 清除正在进行的导航路线,并在控制台记录停止的事件。这一功能使得用户可以在需要时随时中断导航,返回到地图的正常浏览状态。
效果展示

图中的POI都是用户点击上传的钓鱼点,可以看到,页面的四个角一共有五个按钮,对应了不同功能。点击右上角的“搜索鱼类信息”按钮,会弹出进一步的功能窗,该部分主要实现向用户推荐钓鱼点、搜索查询、导航的功能。

获取用户起点:

用户可以基于多种需求组合筛选目的地,系统选择最近目的地,就可开始导航。高德api服务可以方便地展示路径规划和地图路线。当然,也可以视用户需求添加步行、骑车的路径规划实例。

结语
用户的需求日益多样化,尤其是在多个相似目的地中选择时,怎样结合自身需求最快实现路径规划?本文通过LBS(位置服务)思想,我们能够将用户的地理位置与丰富的兴趣点(POI)数据结合起来,为他们提供更加精准、便捷的服务。在这个背景下,本文不仅仅旨在开发钓鱼指南平台,而是探索了一种全新的信息获取方式,向受众范围更加明确的用户提供专业平台,使他们能够轻松找到最近的目标。
不仅仅是“哪个最近的鱼塘既能钓鲫鱼又能钓鲢鱼?”的问题,也可以是“哪个超市最近且同时有新鲜水果和烘焙面包?”、“哪个最近的餐厅既能提供海鲜又有素食菜肴?”、“哪里可以找到最近的咖啡店,同时提供无线网络和桌位?”、“最近的健身房中,哪里有瑜伽课程和力量训练设施?”……在用户没下定主意之前,平台能否根据用户需求提供最近POI的路径规划?
本文只是抛砖引玉,展示了高德api+LBS的广泛应用潜力。作为开发者,可以根据个人兴趣和需求设计出更多具有实用价值的细化服务平台,满足用户在不同场景下的需求,未来这种智能化的服务方式必将覆盖更多生活场景,推动社会资源的合理配置与高效利用,开启更加智能的生活方式。
参考文档
「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!
更多推荐
所有评论(0)