高德开源API花式玩法:租房辅助工具

科技   2024-10-30 14:38   安徽  

来源:juejin.cn/post/7403991780512399387

👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;

截止目前,累计输出 63w+ 字,讲解图 2776+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2300+小伙伴加入

  • 前言
  • 高德公交到达圈的好玩应用
  • 使用AMap.ArrivalRange画出到达圈
  • 在高德地图中使用 turf.js 计算多多边形交集
  • 通过 AMap.PlaceSearch 搜索交集区域的小区
  • 结语
  • 番外

前言

做gis的同学肯定知道等时圈这个东西,即:在一定时间内通过某种出行方式能到达的范围

图片

通过一些计算,我们可以做一些好玩的事情,比如上图通过调用mapbox等时圈接口,计算在蓝色点位附近骑车17分钟可以到达哪些公司或学校。

可能由于国内交通情况更为复杂,做实时性较差的等时圈意义不大,所以高德地图提供了比较稳当的API:公交地铁到达圈,其概念和等时圈类似,你可以选择地铁或公交出行,或者两者兼可,高德接口将计算出可达范围。

高德公交到达圈的好玩应用

用了很久的高德,发现这个功能好像没有被很好的应用,其实高德早在1.4的API中就提供了此功能,最近正好要换个房子,突然想到这个东西正好可以拿来做一个很棒的辅助。

由于我跟我对象上班的地方离得比较远,所以找个折中的地方租房是是很重要的,我准备查询到两个到达圈后,再计算一下重合部分,在重合部分找房,就准确多了。

使用AMap.ArrivalRange画出到达圈

首先我做了一个简单的页面

图片

左上角的面板用来设置参数,可选地铁+公交、地铁、公交三种方式,出行耗时最大支持60分钟(超过了接口会报错),位置需要传入经纬度。

初始化地图的步骤就不用说了,我讲一下这个小应用的使用逻辑。

首先,点击地图时,拾取该位置的经纬度,并通过逆地理接口获取到位置文本

function handleMapClick(e: any) {
  if (!e.lnglat) return
  if (currPositionList.value.length >= 2) {
    autolog.log("最多添加 2 个位置"'error') // 你不会想三个人一起住吧?
    return
  }
  var lnglat = e.lnglat;
  geocoder.getAddress(lnglat, (status: string, result: {
    regeocode: any; info: string;
  }) => {
    if (status === "complete" && result.info === "OK") {
      currPositionList.value.push({ name: result.regeocode.formattedAddress, lnglat: [lnglat.lng, lnglat.lat] })
    }
  });
}

可以看到,我把点选的位置信息,暂时存放到了currPositionList里面,比如你在西二旗上班,而你女朋友在国贸,则点选后效果是这样的

图片

左侧面板新增了两个位置,点击查询时,我将依次查询这两个到达圈,并渲染到地图上

function getArriveRange() {
  let loopCount = 0
  for (let item of currPositionList.value) {
    arrivalRange.search(item.lnglat, currTime.value, (_status: any, result: { bounds: any; }) => {
      map.remove(polygons);
      if (!result.bounds) return
      let currPolygons = []
      loopCount++
      for (let item of result.bounds) {
        let polygon = new AMap.Polygon(polygonStyle[`normal${loopCount}` as "normal1" | "normal2"]);
        polygon.setPath(item);
        currPolygons.push(polygon)
      }
      map.add(currPolygons);
      polygons.push({
        lnglat: item.lnglat,
        polygon: currPolygons,
        bounds: result.bounds
      })
      if (loopCount === currPositionList.value.length) {
        map.setFitView();
      }
    }, { policy: currStrategy.value });
  }
}

由于接口调用方式是以回调函数的形式返回的,所以我这里记录了一下回调次数,当次数满足后,再去调整视角。这段逻辑运行之后,将是如下结果:

图片

很遗憾,你和你的女朋友,下班后的一个小时内见不成面了,这意味着,如果找一个折中的地方租房,你们上班单程通勤,无论如何都超过一个小时了,如果想尽量接近一个小时,那么看下两者的交汇处

图片

大钟寺地铁站将会是个很好的选择。

这样仍需要我们手动去观察,那么能不能算一下两者的交集呢?

在高德地图中使用 turf.js 计算多多边形交集

在上面提到的getArriveRange函数中,我新增了这样的逻辑

if (loopCount === currPositionList.value.length) {
  let poly1 = turf.multiPolygon(toNumber(polygons[0].bounds));
  let poly2 = turf.multiPolygon(toNumber(polygons[1].bounds));
  var intersection = turf.intersect(turf.featureCollection([poly1, poly2]));
  if (intersection) {
    let geojson = new AMap.GeoJSON({
      geoJSON: {
        type"FeatureCollection",
        features: [intersection]
      },
      getPolygon: (_: any, lnglats: any) => {
        return new AMap.Polygon({
          path: lnglats,
          ...polygonStyle.overlap
        });
      }
    });
    polygons.push({
      lnglat: [0, 0],
      polygon: geojson,
      bounds: intersection.geometry.coordinates
    })
    map.add(geojson);
  } else {
    autolog.log("暂无交集,请自行查找"'error')
  }
  map.setFitView();
}

由于高德地图到达圈获取到的经纬度是字符串,放到 turf 里面会报错,所以这里写了一个简单的递归,将多维数组所有的数据都转化为数字。

// 递归的将多维数组内的字符串转为数字
function toNumber(arr: any) {
  return arr.map((item: any) => {
    if (Array.isArray(item)) {
      return toNumber(item)
    } else {
      return Number(item)
    }
  })
}

使用turf.multiPolygon将获取到的多维数组转化为标准的 geojson 格式,以便于 turf 处理,在turf7.x中,turf.intersect的用法稍有改变,需要turf.featureCollection([poly1, poly2])作为参数传入。

这一步操作 turf 将计算并返回两个多多边形的交集intersection(geojson),但是在高德地图API2.0中,直接传入这个geojson会报错(1.4不会),看了下源码,发现高德有一个操作是直接取第 0 个features,导致它识别不了这种格式的数据,所以我们手动处理下,即:

let geojson = new AMap.GeoJSON({
  geoJSON: {
    type"FeatureCollection",
    features: [intersection]
  },
  getPolygon: (_: any, lnglats: any) => {
    return new AMap.Polygon({
      path: lnglats,
      ...polygonStyle.overlap
    });
  }
});

这样,高德就可以正确渲染这个数据了,这里需要注意的是,geojson 虽然也是 AMap.Polygon 构造的,但是需要一个特殊参数:path,没有的话,也不会报错,但是渲染不出来。

渲染完成后是这样的:

图片

使用绿色代表重合部分,说明在这之中找房都是可以的。

通过 AMap.PlaceSearch 搜索交集区域的小区

高德提供了通过多边形区域搜索POI的接口

placeSearch = new AMap.PlaceSearch({ //构造地点查询类
   pageSize: 5, // 单页显示结果条数
   pageIndex: 1, // 页码
   map: map, // 展现结果的地图实例
   autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
 });
 placeSearch.searchInBounds('小区', intersection.geometry.coordinates);
图片

效果如上图所示,这样就可以轻松租房啦!

但是由于此接口是 get 请求,如果交集区域过大,会超出 get 请求长度限制:

图片

结语

这个就叫产品思维,一个简单的API可以延伸出很多有趣的应用。

此仓库已在 github 开源,地址:

https://github.com/LarryZhu-dev/amap_arrivalRange

番外

高德云镜(高德云镜三维重建平台)目前已向企业和政府开放使用(暂未对个人开发者开放)

图片

在web端,高德开发了 Cesium 插件用作展示,但目前来看要求配置过高

  • CesiumJS引擎:CesiumJS v1.117+(建议)
  • 浏览器:Chrome v126+(建议)
  • 显卡:16GB显存以上独立显卡,推荐 NVDIA RTX 4090
  • CPU:2.5 GHz 以上(建议)
  • 内存:32GB 以上(建议)

看起来类似谷歌地球的全量城市建模。

  • 官网:yunjing.amap.com/#/
  • 开发文档:yunjing.amap.com/#/docs

👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;

截止目前,累计输出 63w+ 字,讲解图 2776+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2300+小伙伴加入


1. 我的私密学习小圈子~

2. 自建图床?Minio 太香辣 !

3. 详解三大权限模型

4. 分页查询接口,从2s优化到了0.01s

最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。

“在看”支持小哈呀,谢谢啦

小哈学Java
码龄9年,前某厂中台研发。专注于Java领域干货分享,不限于BAT面试, 算法,数据库,Spring Boot, 微服务,高并发, JVM, Docker容器,ELK相关知识,期待与您一同进步。
 最新文章