@heycar/heycars-map
TypeScript icon, indicating that this package has built-in type declarations

0.11.0-google3 • Public • Published

说明

时间关系,先写个简要文档,之后会补一个全面的文档。

特性

  • 集成 高德 和 谷歌 两个地图
  • 支持 vue 2.7 和 vue 3
  • 统一的接口,不需要写两套

安装

# 安装依赖包
npm install @heycar/heycars-map --save

加载地图样式

import "@heycar/heycars-map/dist/style.css";

自定义字体

目前地图提供了 3 个字体 css variables 用于外部制定特殊字体

/* 使用特殊字体 HarmonyOS_Sans_SC_Regular */
body {
  --HEYCAR_MAP_CSS_VAR_FONT_REGULAR: HarmonyOS_Sans_SC_Regular, "PingFangSC-Regular", "PingFang SC";
  --HEYCAR_MAP_CSS_VAR_FONT_MEDIUM: HarmonyOS_Sans_SC_Medium, "PingFangSC-Medium", "PingFang SC";
  --HEYCAR_MAP_CSS_VAR_FONT_SEMI_BOLD: HarmonyOS_Sans_SC_Bold, "PingFangSC-Semibold", "PingFang SC";
}

使用

常用数据结构

export type Point = [number, number];

export type Place = {
  lng: number;
  lat: number;
  name: string;
  displayName: string;
};

export interface Zone {
  name: string;
  path: Point[];
}

export interface RecommendZonePlaces {
  available?: boolean;
  zone?: Zone;
  places?: Place[];
}

export enum CenterPlaceStatus {
  GEO_LOADING = "GEO_LOADING",
  QUERYING_INFO = "QUERYING_INFO",
  SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
  OK = "OK",
}

在 入口文件添加 MapProvider

  • 对于 jsx/tsx 文件的例子
<MapProvider
  // 高德地图 api key
  amapKey={amapApiKey}
  // 高德地图 secret
  amapSecret={amapApiSecret}
  // 谷歌地图 id
  gmapId={gmapId}
  // 谷歌地图 api key
  gmapKey={gmapApiKey}
  // 使用哪个地图供应商,目前两个供应商: amap 高德 / gmap 谷歌
  supplier={"amap"}
>
  ...
</MapProvider>
  • 对于 vue 文件的例子
<MapProvider
  :gmap-id="gmapId"
  :gmap-key="gmapApiKey"
  :amap-key="amapApiKey"
  :amap-secret="amapApiSecret"
  supplier="amap"
>
   ...
</MapProvider>

在地图里可以使用的组件

为了方便集成,已经将常用业务逻辑集成在四个业务组件里面,下面是推荐使用的业务组件

  • BusinessRecomendPlaceMap
  • BusinessReselectPlaceMap
  • BusinessQuotingMap
  • BusinessTaxiServiceMap
  • BusinessTaxiEndMap

下面三个是推荐搭配使用的业务 hooks

  • useBusinessRecomendPlaceMap
  • useBusinessReselectPlaceMap
  • useBusinessQuotingMap
  • useBusinessTaxiServiceMap

选择上车点和推荐点的地图组件 BusinessRecomendPlaceMap

对于 jsx/tsx 文件的例子

import { defineComponent } from "vue";
import { BusinessRecomendPlaceMap, useBusinessRecomendPlaceMap } from "@heycar/heycars-map";

export default defineComponent({
  setup() {
    const {
      centerPlace,
      mapContext,
      setCenterPlaceByUserSpecified,
      setCenterPlaceByUserSpecifiedInZone,
    } = useBusinessRecomendPlaceMap();
    // 演示 setCenterPlaceByUserSpecifiedInZone 的用法
    const demoForUsage = () => {
      setCenterPlaceByUserSpecifiedInZone({
        // 期望的地图中心点
        place: {
          lng: 139.56,
          lat: 35.56,
          name: "user specified place in zone",
          displayName: "user specified place in zone",
        },
        // 推荐点和绿区信息
        recommends: {
          // 绿区
          zone: {
            name: "zone 1",
            path: [
              [139.569, 35.555],
              [139.558, 35.55],
              [139.56, 35.565],
            ],
          },
          // 绿区内的推荐点列表
          places: [
            {
              lng: 139.56,
              lat: 35.56,
              name: "user specified place in zone",
              displayName: "user specified place in zone",
            },
            {
              lng: 139.562,
              lat: 35.562,
              name: "recommend place 2",
              displayName: "recommend place 2",
            },
          ],
        },
      });
    };
    return () => (
      <BusinessRecomendPlaceMap
        class={"demo"}
        geoLoadingTitle={"正在获取您当前的位置"}
        unavailableTitle={"当前区域暂未开通服务"}
        emptyTitle={"当前位置"}
        queryingTitle={"正在获取地址信息"}
        recomendDescription={"您将在此处上车"}
        geoErrorOnceNotificationKey="BusinessReselectPlaceMap_GeoErrorOnceKey"
        defaultCenterPlace={(place) =>
          place ?? {
            lng: 139.777777,
            lat: 35.777777,
            name: "default place name",
            displayName: "default place displayName",
          }
        }
        getAvailable={() => Promise.resolve(true)}
        getRecomendPlace={getRecomendPlace}
        getDefaultCenterPlace={getDefaultCenterPlace}
        renderPlacePhoto={(place) => {
          place;
          return "https://oss-now.heycars.cn/image/graphicGuidance/file/hmlh38_xs6_DdksNX0_TbgF0lKXp.jpg";
        }}
        renderPlaceTag={(place) => {
          place;
          return "最近使用";
        }}
        mapContext={mapContext}
        onChangePlace={(place) => {
          console.log("地图中心点变化时触发 place = ", place);
        }}
        onChangeRecomandPlace={({ place, inputPlace, isInZone }) => {
          console.log("用户操作地图,计算推荐点后得出的最终位置时触发,此时可以向后端查询城市信息");
          console.log(
            "计算推荐点之前的地址是: ",
            inputPlace,
            " 最终的地址是: ",
            place,
            " 是否在绿区内: ",
            isInZone,
          );
        }}
        onClickLocatorText={() =>
          console.log("用户点击了蓝色光标文字触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onClickLocatorPhoto={() =>
          console.log("用户点击了蓝色光标图片触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onGeoError={() => {
          console.log("获取GPS失败时触发,此时可以弹框告诉用户");
        }}
        onGeoErrorOnce={(isBusinessTimeout) => {
          console.log(
            "获取GPS失败时触发, 只触发一次, ",
            isBusinessTimeout ? "给用户超时提示" : "给用户无权限反馈",
          );
        }}
      />
    );
  },
});

选择上车点和推荐点的地图组件 BusinessReselectPlaceMap

对于 jsx/tsx 文件的例子

import { defineComponent } from "vue";
import { BusinessReselectPlaceMap, useBusinessReselectPlaceMap } from "@heycar/heycars-map";

export default defineComponent({
  setup() {
    const {
      centerPlace,
      mapContext,
      setCenterPlaceByUserSpecified,
      setCenterPlaceByUserSpecifiedInZone,
    } = useBusinessReselectPlaceMap();
    // 演示 setCenterPlaceByUserSpecifiedInZone 的用法
    const demoForUsage = () => {
      setCenterPlaceByUserSpecifiedInZone({
        // 期望的地图中心点
        place: {
          lng: 139.56,
          lat: 35.56,
          name: "user specified place in zone",
          displayName: "user specified place in zone",
        },
        // 推荐点和绿区信息
        recommends: {
          // 绿区
          zone: {
            name: "zone 1",
            path: [
              [139.569, 35.555],
              [139.558, 35.55],
              [139.56, 35.565],
            ],
          },
          // 绿区内的推荐点列表
          places: [
            {
              lng: 139.56,
              lat: 35.56,
              name: "user specified place in zone",
              displayName: "user specified place in zone",
            },
            {
              lng: 139.562,
              lat: 35.562,
              name: "recommend place 2",
              displayName: "recommend place 2",
            },
          ],
        },
      });
    };
    return () => (
      <BusinessReselectPlaceMap
        class={"demo"}
        unavailableTitle={"当前区域暂未开通服务"}
        emptyTitle={"当前位置"}
        queryingTitle={"正在获取地址信息"}
        recomendDescription={"您将在此处上车"}
        // 对于同一个 geoErrorOnceNotificationKey
        // geoErrorOnce 事件在 geoErrorOnceNotificationInterval 时间间隔内全局只会触发一次
        geoErrorOnceNotificationKey="BusinessReselectPlaceMap"
        defaultPlace={{
          lng: 139.777777,
          lat: 35.777777,
          name: "default place name",
          displayName: "default place display name",
        }}
        getAvailable={() => Promise.resolve(true)}
        getRecomendPlace={async ({ lng, lat }) => {
          // 向后端获取推荐点信息
          return {
            // 服务是否可用
            available: true,
            // 绿区
            zone: {
              name: "绿区名称",
              path: [
                [lng - 0.001, lat + 0.001],
                [lng, lat - 0.001],
                [lng + 0.001, lat + 0.0005],
              ],
            },
            // 推荐点列表
            places: [
              { lat: lat - 0.00001, lng: lng + 0.0001, name: "place 1", displayName: "place 1" },
              { lat: lat - 0.0002, lng: lng + 0.0002, name: "place 2", displayName: "place 2" },
              { lat: lat - 0.0002, lng: lng - 0.0001, name: "place 3", displayName: "place 3" },
            ],
          };
        }}
        onChangeRecomandPlace={({ place, inputPlace, isInZone }) => {
          console.log("用户操作地图,计算推荐点后得出的最终位置时触发,此时可以向后端查询城市信息");
          console.log(
            "计算推荐点之前的地址是: ",
            inputPlace,
            " 最终的地址是: ",
            place,
            " 是否在绿区内: ",
            isInZone,
          );
        }}
        onClickLocatorText={() =>
          console.log("用户点击了蓝色光标文字触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onClickLocatorPhoto={() =>
          console.log("用户点击了蓝色光标图片触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onGeoError={() => {
          console.log("获取GPS失败时触发,此时可以弹框告诉用户");
        }}
        onGeoErrorOnce={(isBusinessTimeout) => {
          console.log(
            "获取GPS失败时触发, 只触发一次, ",
            isBusinessTimeout ? "给用户超时提示" : "给用户无权限反馈",
          );
        }}
      />
    );
  },
});

询价业务的地图组件 BusinessQuotingMap

对于 jsx/tsx 文件的例子

import { defineComponent } from "vue";
import { BusinessQuotingMap, useBusinessQuotingMap } from "@heycar/heycars-map";

export default defineComponent({
  setup() {
    const { setMap, registerFitVeiw } = useBusinessQuotingMap();
    return () => (
      <BusinessQuotingMap
        class={"demo"}
        from={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.311295,
          lng: 103.841974,
        }}
        to={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.2966426,
          lng: 103.7763939,
        }}
        fromDescription={"您将在此上车"}
        renderDescription={({ distance, duration, tolls }) =>
          `全程 *${distance / 1000}公里*  约行驶 *${duration}* 高速费用 *${tolls ?? 0}*元`
        }
        mapRef={setMap}
        registerOverlay={registerFitVeiw}
        onClickStartPoint={(place) => console.log("点击起点时触发 palce = ", place)}
        onClickEndPoint={(place) => console.log("点击终点时触发 palce = ", place)}
      />
    );
  },
});

打车状态流转业务的地图组件 BusinessTaxiServiceMap

对于 jsx/tsx 文件的例子

import { defineComponent } from "vue";
import { BusinessTaxiServiceMap, useBusinessTaxiServiceMap } from "@heycar/heycars-map";

export default defineComponent({
  setup() {
    const { setMap, registerFitVeiw } = useBusinessTaxiServiceMap();
    return () => (
      <BusinessTaxiServiceMap
        class={css.adjustedDemo}
        from={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.311295,
          lng: 103.841974,
        }}
        to={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.2966426,
          lng: 103.7763939,
        }}
        driverStatus={"driverArrived"}
        bookDispatchingTitle="2月14日 11:00 用车"
        dispatchingTitle="正在为您搜索附近司机"
        driverArrivedTitle="司机已等待 00:35"
        renderStartSerivceTitle={({ distance, duration }) =>
          `距你*${distance}*公里, *${duration}*分钟`
        }
        renderInServiceTitle={({ distance, duration }) =>
          `距离终点*${distance}*公里, 预计*${duration}*分钟`
        }
        getDriverPositionTrack={async () => {
          //  向后端请求司机的历史轨迹
          return Promise.resolve<TrackPoint[]>([
            { lng: 121.4036983, lat: 31.216324, angle: 30, timestamp: 1698058438000 },
            { lng: 121.4036983, lat: 31.216324, angle: 30, timestamp: 1698058439000 },
            { lng: 121.403581, lat: 31.216415, angle: 30, timestamp: 1698058442000 },
          ]);
        }}
        interval={5000}
        mapRef={setMap}
        registerOverlay={registerFitVeiw}
      />
    );
  },
});

服务结束的地图组件

对于 jsx/tsx 文件的例子

import { defineComponent } from "vue";
import { BusinessTaxiEndMap } from "@heycar/heycars-map";

export default defineComponent({
  setup() {
    return () => (
      <BusinessTaxiEndMap
        class={"demo"}
        from={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.311295,
          lng: 103.841974,
        }}
        to={{
          displayName: "ARTS LINK零创国际艺术教育长宁区创业园区",
          name: "上海市长宁区华阳路街道ARTS LINK零创国际艺术教育长宁区创业园区",
          lat: 1.2966426,
          lng: 103.7763939,
        }}
      />
    );
  },
});

下面是基础业务组件的使用方法,但是目前阶段不推荐使用

下列是一些更加基础的业务组件, 虽然导出了,但是目前阶段不推荐使用

  • AbsoluteAddressBox
  • DrivingLine
  • PassengerCircle
  • PlaceCircle
  • StartEndPoint
  • TaxiCar
  • WalkingLine
  • WaveCircle
  • DrivingRoute
  • WalkingRoute
  • PickupPoints

在地图里使用 AddressBox ,需要放在 HeycarMap 内部

<HeycarMap center={[0, 0]} zoom={3}>
  ...
  <AddressBox position={[0, 0]} title={"Martyrs Lawn"} description={"您将在此处上车"} />
  ...
</HeycarMap>
  • 对于 vue 文件的例子
<HeycarMap :center="[0, 0]" class="any class name" :zoom="3">
   <template #fallback>error</template>
   <template #loading>loading</template>
   ...
   <AddressBox title="Martyrs Lawn" :position="[0, 0]" description="您将在此处上车" >
   </AddressBox>
   ...
</HeycarMap>

HeycarMap 的基本用法

  • 对于 jsx/tsx 文件的例子
<HeycarMap
  class="any class name"
  // 地图加载失败要显示的内容
  fallback={() => <div>error</div>}
  // 地图还没有加载完成时要显示的内容
  loading={() => <div>loading</div>}
  // 地图中心点
  center={[0, 0]}
  // 地图放缩
  zoom={3}
>
  ...
</HeycarMap>
  • 对于 vue 文件的例子
<HeycarMap :center="[0, 0]" class="any class name" :zoom="3">
   <template #fallback>error</template>
   <template #loading>loading</template>
   ...
</HeycarMap>

关于 enableAuxiliaryGraspRoad 模式

enableAuxiliaryGraspRoad 模式适用场景:

  • 测试司机位置偏移 的优化效果
  • 目前只能在国内打车,测试优化效果。
  • 目前只能用 splytech 供应商进行测试。

测试时的注意点:

  1. 起点和终点 在 splytech 后台系统地图上的位置是错误的。

为了方便测试 司机位置偏移 的优化效果,在 enableAuxiliaryGraspRoad 模式下会显示下列辅助信息:

  1. 会显示两个导航路线,蓝色跟设计稿样式一致的是原来的导航路径,红色的是司机位置纠偏以后计算的导航路径。
  2. 会显示两个车辆,跟设计稿样式一致的是原来的车辆,虚影的车辆是司机位置纠偏以后的车辆。
  3. 会将供应商提供的司机位置显示为蓝色标记,辅助观察供应商提供的司机位置。
  4. 会显示一条黑色的路径,表示将供应商提供的位置纠偏以后的路径。
  5. enableAuxiliaryGraspRoad 模式下,为了方便测试,取消了屏幕 15 秒自动调整功能。

Readme

Keywords

none

Package Sidebar

Install

npm i @heycar/heycars-map

Weekly Downloads

120

Version

0.11.0-google3

License

none

Unpacked Size

8.62 MB

Total Files

842

Last publish

Collaborators

  • kuangweihang
  • alan1034
  • situgl
  • lldf1984
  • xinchaobeta