WebGIS开发入门到进阶 | 高德地图打卡功能实现教程
前面我们学习了监听地图的click事件,实现了在地图上点击新增热门标记点的功能。那么这节前面我们学习了监听地图的click事件,实现了在地图上点击新增热门标记点的功能。那么这节课,我们利用上一节 GeoJSON 数据持久化来实现标记点的保存功能,以实现打卡功能——能在标记点显示打卡次数,标记点不会消失,就算重启浏览器也能保存。
那么怎么来实现打卡功能呢?这就需要监听标记点的点击事件了。今天我们要实现的是监听标记点的点击事件,语法与监听地图点击事件非常相似。
一、监听标记点的点击事件
现在就来实现下监听标记点的点击事件,一样的语法:
marker.on('click', function(e) { // 点击标记时执行的代码 })当点击标记时,就能启动 function 中的代码。这里的marker就是我们创建或已有的标记点对象。
为了保存打卡次数,需要对标记点进行属性赋值,这时候就需要对 GeoJSON 进行修改。在创建标记时,我们通过extData来添加自定义属性:
var marker = new AMap.Marker({ // 创建标记 position: e.lnglat, extData: { _geoJsonProperties: { gid: geojson.getOverlays().length + 1, click: 0, } } })这里设置了gid就是标记序号属性,从 1 开始;还有点击属性click,用来记录点击次数,初始值为 0。需要注意的是,_geoJsonProperties是 GeoJSON 数据中用来存储自定义属性的标准字段名,高德地图 SDK 在导入导出 GeoJSON 时会自动识别这个字段。
二、为新标记点绑定点击事件
创建 marker 后,还要给 marker 创建绑定事件。注意,这是写在map.on('click')事件中的。语法就是上面的写法:
map.on('click', function(e) { // 创建标记 var marker = new AMap.Marker({ position: e.lnglat, extData: { _geoJsonProperties: { gid: geojson.getOverlays().length + 1, click: 0, } } }) // 为新标记绑定点击事件 marker.on('click', function(e) { // 点击时执行的逻辑 }) })这样,就只有对新创建的 marker 才绑定了点击事件。每次用户点击地图新增一个标记时,这个新标记就拥有了点击打卡的功能。
三、为旧标记点绑定点击事件
但是,对于已有的 marker 就没办法监听了。因为上面这种方式只对新创建的标记有效,那些已经保存在本地、重启浏览器后重新加载出来的旧标记点,还没有绑定点击事件。
这时候,还要对已有的 marker 绑定。已有的 marker 都是通过importData的方式拿到的。这时候就需要在导入的时候,就对这些已有的数据进行绑定点击事件:
// 导入数据 if (JSON.stringify(getData()) != '[]') { // 判断 localStorage 是否有数据 geojson.importData(getData()) // 导入数据 geojson.eachOverlay(function(item) { // 遍历所有标记 item.on('click', function(e) { // 为每个标记绑定点击事件 console.log(e) }) }) map.add(geojson) // 将 geojson 添加到地图 }函数里的item就是旧的数据的每一项,这样就给每个 marker 都绑定点击事件了。这里eachOverlay是 GeoJSON 对象提供的一个遍历方法,它会依次处理 geojson 中的每一个覆盖物(即每一个标记点)。
四、实现打卡次数累加逻辑
设置好事件后,就需要实现,当用户点击标记时,点击属性加 1。这时候就在事件中实现:
var ext = marker.getExtData() // 获取扩展数据 var click = ++ext._geoJsonProperties.click // 点击次数加 1这个意思就是先获取 extData 属性值赋予 ext 变量,然后从中提取click属性,当点击时候,就加 1,然后赋值给 click 变量。
同样的内容,也得给旧标记点再来一次,复制过去即可:
item.on('click', function(e) { var ext = item.getExtData() var click = ++ext._geoJsonProperties.click }这就实现了新旧点在点击时都能让click属性加 1。
注意:如果调试时,需要先把已有的 geojson 存储删除,因为这里已经改变了 geojson 的结构,已有的数据是没有这些属性的。可以在浏览器控制台执行localStorage.removeItem('geoData')来清除旧数据。
五、数据持久化保存
实现上述步骤后,还有个问题,就是click的值并没有实现在本地存储 geojson 数组中的保存。也就是说,虽然点击时内存中的click值增加了,但如果刷新页面,打卡次数会丢失。
所以还得加上一句:
saveData(geojson.toGeoJSON())这样才能实现在 localStorage 中的保存。geojson.toGeoJSON()方法会将当前所有标记点及其属性数据导出为标准 GeoJSON 格式,然后通过saveData函数存储到浏览器本地。
同样的这个操作也需要在新旧标记都要进行一遍:
新标记的点击事件:
marker.on('click', function(e) { var ext = marker.getExtData() var click = ++ext._geoJsonProperties.click saveData(geojson.toGeoJSON()) // 保存到本地 })旧标记的点击事件:
item.on('click', function(e) { var ext = item.getExtData() var click = ++ext._geoJsonProperties.click saveData(geojson.toGeoJSON()) // 保存到本地 })六、使用信息窗口显示打卡次数
这样就实现了打卡功能,但是,打卡次数现在是在控制台输出的,如何让用户看见呢?这样就需要使用信息框了。
思路就是把console.log替换成消息框的显示模式:
// 使用消息提示框 var infowindow = new AMap.InfoWindow({ anchor: 'top-center', // 信息窗口锚点位置 content: `<div>打卡了${click}次</div>` // 模板字符串显示打卡次数 })这里使用了 ES6 的模板字符串语法,将click变量的值动态嵌入到 HTML 内容中。anchor: 'top-center'表示信息窗口的锚点位于顶部中间位置。
这样来实现消息的显示,注意,这个也是在map.on里实现的。接下来就是显示:
// 打开信息窗 infowindow.open(map, marker.getPosition())就是实现了消息窗在哪里显示。marker.getPosition()获取标记点的经纬度坐标,信息窗口就会在这个位置弹出。
当然,新旧标记都要来实现一遍:
新标记的完整点击事件:
marker.on('click', function(e) { var ext = marker.getExtData() var click = ++ext._geoJsonProperties.click saveData(geojson.toGeoJSON()) var infowindow = new AMap.InfoWindow({ anchor: 'top-center', content: `<div>打卡了${click}次</div>` }) infowindow.open(map, marker.getPosition()) })旧标记的完整点击事件:
item.on('click', function(e) { var ext = item.getExtData() var click = ++ext._geoJsonProperties.click saveData(geojson.toGeoJSON()) var infowindow = new AMap.InfoWindow({ anchor: 'top-center', content: `<div>打卡了${click}次</div>` }) infowindow.open(map, item.getPosition()) })七、常见问题解答
7.1 为什么点击标记时候,不会触发地图的 click 事件?
这是一个容易被忽略的问题。在高德地图中,点击标记点时,事件被标记捕获并处理,不会冒泡到地图层。因此,map.on('click')事件不会被触发。这正是为什么我们需要单独为标记点绑定click事件来处理打卡逻辑。
7.2 调试时需要注意什么?
如果调试时发现旧标记点点击没有反应,或者打卡次数不显示,可能是因为之前存储的 GeoJSON 数据中没有_geoJsonProperties这个属性结构。建议在调试前先清除已有的本地存储数据,然后在控制台执行location.reload()刷新页面,重新添加标记点进行测试。
八、总结
通过本节课的学习,我们实现了以下功能:
✅ 通过marker.on('click')监听标记点的点击事件
✅ 使用extData._geoJsonProperties为标记点添加click属性记录打卡次数
✅ 通过geojson.eachOverlay()遍历旧标记点并绑定点击事件
✅ 使用geojson.toGeoJSON()和saveData()实现数据的持久化保存
✅ 使用AMap.InfoWindow在标记点位置显示打卡次数信息
至此,一个完整的打卡功能就实现了。用户添加的每个标记点都支持打卡记录,次数会累加显示,并且所有数据在浏览器重启后依然存在。
大家可以先自己上手尝试看看。如果有不明白或者看不懂的地方戳我👇
WebGIS开发零基础入门系列教程持续更新中,关注我们不错过后面的内容更新
