(已开源)基于高德SDK 、Api,实现纯H5的精准坐标选址工具

1,439 阅读3分钟

背景

一期端版本基础功能

整个选址工具做成一个单独维护的项目,通过端上能力,跨页面访问,通信并返回最终数据结果。

功能分析

其中借助端上的能力有:

  • openPage 新开页面
  • exitPage 退出容器
  • getLocation 获取(火星坐标)经纬度
  • nativePostMsgToJs 通信手段

替代方案思考

1. 原openPage、exitPage 的功能实现

  • 先想到的是router新开路由、回退路由来模拟(N) 原因:页面进退会触发刷新,对表单场景不友好,页面需要缓存体验不好,通信繁琐可能出问题
  • 放入弹框里,控制弹框开关渲染地图(N) 原因:有点死板,可定制程度不够,需要自己单独写完整调用流程
  • 嵌入iframe ,控制iframe 的加载和移除(Y) 原因:避免了新开页面的弊端,可自定义iframe渲染位置,为后面通信做铺垫

2. 原getLocation 的功能实现

端版本做的时候,是为了尽量精确的获取到当前坐标,所以通过端获取实时的火星坐标

2.1 存在问题:

  1. 弱网情况下高德,回到当前位置的Api 会存在延迟
  2. 回到当前位置的logo对乡村老人而已不够明显,调用也存在延迟
  3. 坐标精度不够高

2.2 方案

  1. 页面刚渲染时候,通过Api先获取坐标,存起来后期只操作坐标保证后面的操作不卡顿
  2. 模拟返回当前位置,并给出明显提示,剔除了每次点击调用Api的延迟问题
  3. 获取坐标Api的参数进行精度参数配置

3. 原nativePostMsgToJs 通信手段的实现

因为这个选址工具我是作为单独项目维护,所以调用时参数都是通过url传递

  • 使用本地缓存通信也是可以的,但存在局限性(菜鸟域名),不够灵活 在上面模拟端上容器渲染时采用了iframe进行加载,也是考虑到跨项目之间的通信问题 所以采用了postMessage 来进行通信,保障所以业务项目都能使用
// 动态创建或写死一个iframe 加载组件
const addIframe = useCallback(
    (data) => {
      let url = `${mapEnv}?h5=true&key=${data.key}&desc=${data.desc}&v=${data.v}&title=${data.title}&zoom=${data.zoom}&serverKey=${data.serverKey}&location=${data.location}#/`;
      var iframe = document.createElement('iframe');
      iframe.src = url;
      document.body.append(iframe);
    },
    []
  );
  const onCancle = () => { }
  const onOk = () => { }
  const cbMessage = useCallback(
    (e: any) => {
      console.log(e.data, 'eeeeecb---Message');
      if (!e || !e.data) {
        return;
      }
      if (e.data.cancle) {
        onCancle();
      } else {
        onOk(e.data);
      }
    },
    [onCancle, onOk]
  );
  useEffect(() => {
addIframe(data)
    window.addEventListener('message', (e) => cbMessage(e), false);
    return window.removeEventListener('message', (e) => cbMessage(e), false);
  }, [data,cbMessage]);

深度优化封装

虽然整个地图被封装成了单独的模块,但对于使用纯H5版本的用户,使用起来还是有一丢丢麻烦。 考虑到--尽量让使用者开箱即用,不考虑多余的逻辑处理,所以为H5使用者单独封装了个组件包。

1. map-site

@alife/map-site

2. 该组件提供的能力

  • 地图自定义渲染区域
  • 端版本所有的能力参数配置
  • 统一iframe的唤起和销毁
  • 统一的通信方式和事件回调
// 调用方式
import H5Map from '@alife/map-site'

<H5Map
        id="h5_iframe"
        visible={visible}
        showArea="my_map"
        params={{
          key: 'fb0cf7c70e6d139a2fe7d4b02af40a46',
          desc: '11如未选中周边信息,最终以标记点坐标为准。',
          v: '2.0',
          title: '选址demo',
          zoom: '15',
          serverKey: '8e5a71262cda4c03862279b0b9849515',
          location: result ? result.location : '120.154066,30.290777',
        }}
        onCancle={() => {
          setVisibile(false);
          console.log('on calcle');
        }}
        onOk={(e: any) => {
          setResult(e);
          setVisibile(false);
          console.log(e, 'onOk cb');
        }}
      />

这样大家就不需要关注多余的逻辑处理,全部交给这层中间组件进行统一处理

3. 效果图展示

整体的样式跟端版本是一样的,尽量抹平差异保持一致

3.1 局部自定义区域渲染(自定义渲染id)

3.2 全屏渲染(默认全屏渲染)

欢迎大家接入体验,提出宝贵意见

整体的样式跟端版本是一样的,尽量抹平差异保持一致

@alife/map-site

@alife/map-site:https://web.npm.alibaba-inc.com/package/@alife/map-site

gitHub已经开源

纯H5版代码开源:https://github.com/babybrotherzb