npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@heycar/heycars-map

v2.5.3

Published

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

Downloads

448

Readme

说明

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

特性

  • 集成 高德 和 谷歌 两个地图
  • 支持 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 CoordinateType = "wgs84" | "gcj02" | "bd09";

export type CoordinatePoint = {
  lng: number;
  lat: number;
  type: CoordinateType;
};

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

export interface CoordinateZone {
  name: string;
  path: CoordinatePoint[];
}

export interface CoordinateRecommendZonePlaces {
  // 是否强制吸附
  adsorption?: boolean;
  type?: RecommendType;
  // 是否可以提供服务
  available?: boolean;
  zone?: CoordinateZone;
  places?: CoordinatePlace[];
}

export interface CoordinateValueOfOnChangeRecommendPlace {
  type: RecommendType;
  isSameZone: boolean;
  place: CoordinatePlace;
  inputPlace: CoordinatePlace;
  zone?: CoordinateZone;
}

export interface CoordinateGeoPosition {
  position: CoordinatePoint;
  coords?: GeolocationCoordinates;
}

export interface CoordinateTrackPoint {
  lng: number;
  lat: number;
  type: CoordinateType;
  angle?: number;
  speed?: number;
  timestamp: number;
}

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

export type GoogleConnectionStatus = "pending" | "connected" | "unconnected";

// GeolocationPositionError 类型参考 [MDN Reference](https://developer.mozilla.org/docs/Web/API/GeolocationPositionError)
export interface BusinessGeolocationPositionError extends GeolocationPositionError {
  // isBusinessTimeout 是产品定义的 业务超时,不同于标准 GeolocationPositionError 的TIMEOUT
  // 参考 http://p.heycars.cn/zentaopms/www/index.php?m=story&f=view&storyID=1212
  // 参考 https://doc.weixin.qq.com/doc/w3_AZIAowasAIcGieCNESnQZe1rhTyaK?scode=ACcAmge7AAou1TTqYiAZIAowasAIc
  isBusinessTimeout: boolean;
}

// Restricted(绿区)Forbidden(红区)Recommend(推荐点)
export type RecommendType = "Restricted" | "Forbidden" | "Recommend";

在 入口文件添加 MapProvider

  • 对于 jsx/tsx 文件的例子
<MapProvider
  // 高德地图 api key
  amapKey={amapApiKey}
  // 高德地图 secret
  amapSecret={amapApiSecret}
  // 谷歌地图 id
  gmapId={gmapId}
  // 谷歌地图 api key
  gmapKey={gmapApiKey}
  // 使用哪个地图供应商,目前两个供应商: amap 高德 / gmap 谷歌
  supplier={"amap"}
  // 地图加载失败时显示的标题
  renderLoadFailedTitle={() => (supplier === "gmap" ? "未能成功访问谷歌地图" : "高德地图加载失败")}
  // 地图加载失败时显示的描述
  renderLoadFailedDescription={() =>
    supplier === "gmap" ? "请确认您的网络能正常访问谷歌地图, \n或切回高德地图" : undefined
  }
>
  ...
</MapProvider>
  • 对于 vue 文件的例子
<MapProvider
  :gmap-id="gmapId"
  :gmap-key="gmapApiKey"
  :amap-key="amapApiKey"
  :amap-secret="amapApiSecret"
  supplier="amap"
  render-load-failed-title='() => supplier === "gmap" ? "未能成功访问谷歌地图" : "高德地图加载失败"'
  render-load-failed-description='() => supplier === "gmap" ? "请确认您的网络能正常访问谷歌地图,\n或切回高德地图" : undefined'
>
   ...
</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,
          type: "gcj02",
          name: "user specified place in zone",
          displayName: "user specified place in zone",
        },
        // 推荐点和绿区信息
        recommends: {
          // 绿区
          zone: {
            name: "zone 1",
            path: [
              { lng: 139.569, lat: 35.555, type: "gcj02" },
              { lng: 139.558, lat: 35.55, type: "gcj02" },
              { lng: 139.56, lat: 35.565, type: "gcj02" },
            ],
          },
          // 绿区内的推荐点列表
          places: [
            {
              lng: 139.56,
              lat: 35.56,
              type: "gcj02",
              name: "user specified place in zone",
              displayName: "user specified place in zone",
            },
            {
              lng: 139.562,
              lat: 35.562,
              type: "gcj02",
              name: "recommend place 2",
              displayName: "recommend place 2",
            },
          ],
        },
      });
    };
    return () => (
      <BusinessRecomendPlaceMap
        class={"demo"}
        geoLoadingTitle={"正在获取您当前的位置"}
        unavailableTitle={"当前区域暂未开通服务"}
        forbiddenTitle={"当前区域不可叫车"}
        emptyTitle={"当前位置"}
        queryingTitle={"正在获取地址信息"}
        recomendDescription={"您将在此处上车"}
        geoErrorOnceNotificationKey="BusinessReselectPlaceMap_GeoErrorOnceKey"
        defaultCenterPlace={(place) =>
          place ?? {
            lng: 139.777777,
            lat: 35.777777,
            type: "gcj02",
            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, type, zone }) => {
          console.log("用户操作地图,计算推荐点后得出的最终位置时触发,此时可以向后端查询城市信息");
          console.log(
            "计算推荐点之前的地址是: ",
            inputPlace,
            " 最终的地址是: ",
            place,
            " 推荐类型: ",
            type,
            "绿区(或红区):",
            zone,
          );
        }}
        onClickLocatorText={() =>
          console.log("用户点击了蓝色光标文字触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onClickLocatorPhoto={() =>
          console.log("用户点击了蓝色光标图片触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onGeoError={({ 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,
          type: "gcj02",
          name: "user specified place in zone",
          displayName: "user specified place in zone",
        },
        // 推荐点和绿区信息
        recommends: {
          // 绿区
          zone: {
            name: "zone 1",
            path: [
              { lng: 139.569, lat: 35.555, type: "gcj02" },
              { lng: 139.558, lat: 35.55, type: "gcj02" },
              { lng: 139.56, lat: 35.565, type: "gcj02" },
            ],
          },
          // 绿区内的推荐点列表
          places: [
            {
              lng: 139.56,
              lat: 35.56,
              type: "gcj02",
              name: "user specified place in zone",
              displayName: "user specified place in zone",
            },
            {
              lng: 139.562,
              lat: 35.562,
              type: "gcj02",
              name: "recommend place 2",
              displayName: "recommend place 2",
            },
          ],
        },
      });
    };
    return () => (
      <BusinessReselectPlaceMap
        class={"demo"}
        unavailableTitle={"当前区域暂未开通服务"}
        forbiddenTitle={"当前区域不可叫车"}
        emptyTitle={"当前位置"}
        queryingTitle={"正在获取地址信息"}
        recomendDescription={"您将在此处上车"}
        // 对于同一个 geoErrorOnceNotificationKey
        // geoErrorOnce 事件在 geoErrorOnceNotificationInterval 时间间隔内全局只会触发一次
        geoErrorOnceNotificationKey="BusinessReselectPlaceMap"
        defaultPlace={{
          lng: 139.777777,
          lat: 35.777777,
          type: "gcj02",
          name: "default place name",
          displayName: "default place display name",
        }}
        getAvailable={() => Promise.resolve(true)}
        getRecomendPlace={async ({ lng, lat, type }) => {
          // 向后端获取推荐点信息
          return {
            // 服务是否可用
            available: true,
            // 推荐类别
            type: "Restricted",
            // 绿区
            zone: {
              name: "绿区名称",
              path: [
                { lng: lng - 0.001, lat: lat + 0.001, type },
                { lng: lng, lat: lat - 0.001, type },
                { lng: lng + 0.001, lat: lat + 0.0005, type },
              ],
            },
            // 推荐点列表
            places: [
              {
                lat: lat - 0.00001,
                lng: lng + 0.0001,
                type,
                name: "place 1",
                displayName: "place 1",
              },
              {
                lat: lat - 0.0002,
                lng: lng + 0.0002,
                type,
                name: "place 2",
                displayName: "place 2",
              },
              {
                lat: lat - 0.0002,
                lng: lng - 0.0001,
                type,
                name: "place 3",
                displayName: "place 3",
              },
            ],
          };
        }}
        onChangeRecomandPlace={({ place, inputPlace, type, zone }) => {
          console.log("用户操作地图,计算推荐点后得出的最终位置时触发,此时可以向后端查询城市信息");
          console.log(
            "计算推荐点之前的地址是: ",
            inputPlace,
            " 最终的地址是: ",
            place,
            " 推荐类型: ",
            type,
            "绿区(或红区):",
            zone,
          );
        }}
        onClickLocatorText={() =>
          console.log("用户点击了蓝色光标文字触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onClickLocatorPhoto={() =>
          console.log("用户点击了蓝色光标图片触发,此时可以执行用户点击起点输入框相同的逻辑")
        }
        onGeoError={({ isBusinessTimeout }) => {
          console.log(
            "获取GPS失败时触发,此时可以弹框告诉用户",
            isBusinessTimeout ? "给用户超时提示" : "给用户无权限反馈",
          );
        }}
      />
    );
  },
});

询价业务的地图组件 BusinessQuotingMap

对于 jsx/tsx 文件的例子

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

export default defineComponent({
  setup() {
    const { mapContext, toAmapCoordinateType } = useBusinessQuotingMap();
    return () => (
      <div>
        <BusinessQuotingMap
          class={"demo"}
          from={{
            displayName: "The Malayan Council",
            name: "10 Winstedt Rd, #01-17, Singapore 227977",
            type: "wgs84",
            lat: 1.311295,
            lng: 103.841974,
          }}
          to={{
            displayName: "CDG Engie Charging Station",
            name: "21 Kent Ridge Rd, Singapore 119220",
            type: "wgs84",
            lat: 1.2966426,
            lng: 103.7763939,
          }}
          fromDescription={"您将在此上车"}
          renderDescription={({ distance, duration, tolls }) =>
            `全程 *${distance / 1000}公里*  约行驶 *${duration}* 高速费用 *${tolls ?? 0}*元`
          }
          mapContext={mapContext}
          onClickStartPoint={(place) => console.log("点击起点时触发 palce = ", place)}
          onClickEndPoint={(place) => console.log("点击终点时触发 palce = ", place)}
          onChangeGoogleConnection={(status) =>
            // 根据目前的产品需求,连通性检测只会被检测一次。
            console.log("谷歌连通性发生变化时触发,连通性状态是:", status)
          }
        />
        <div>
          经度 103.841974, 纬度 1.311295 在高德地图上的坐标类型是:
          {toAmapCoordinateType([103.841974, 1.311295])}
      </div>
      <div>
    );
  },
});

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

对于 jsx/tsx 文件的例子

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

export default defineComponent({
  setup() {
    const { mapContext } = useBusinessTaxiServiceMap();
    return () => (
      <BusinessTaxiServiceMap
        class={css.adjustedDemo}
        from={{
          displayName: "The Malayan Council",
          name: "10 Winstedt Rd, #01-17, Singapore 227977",
          type: "wgs84",
          lat: 1.311295,
          lng: 103.841974,
        }}
        to={{
          displayName: "CDG Engie Charging Station",
          name: "21 Kent Ridge Rd, Singapore 119220",
          type: "wgs84",
          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, type: "gcj02", angle: 30, timestamp: 1698058438000 },
            { lng: 121.4036983, lat: 31.216324, type: "gcj02", angle: 30, timestamp: 1698058439000 },
            { lng: 121.403581, lat: 31.216415, type: "gcj02", angle: 30, timestamp: 1698058442000 },
          ]);
        }}
        interval={5000}
        mapContext={mapContext}
      />
    );
  },
});

服务结束的地图组件

对于 jsx/tsx 文件的例子

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

export default defineComponent({
  setup() {
    return () => (
      <BusinessTaxiEndMap
        class={"demo"}
        from={{
          displayName: "樟宜机场",
          name: "樟宜机场",
          lat: 1.35019,
          lng: 103.994003,
          type: "wgs84",
        }}
        to={{
          lat: 1.346493,
          lng: 103.746209,
          name: "长城美华 Coffee Shop (CCMW)",
          displayName: "长城美华 Coffee Shop (CCMW)",
          type: "wgs84",
        }}
      />
    );
  },
});

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

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

  • 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 秒自动调整功能。

下面是地图导出的一些基本工具

import { isCoordinatePointEqual } from "@heycar/heycars-map";

// 比较两个带有坐标类型的点是否为同一个点
isCoordinatePointEqual(
  { type: "gcj02", lng: 114.215114, lat: 22.215972 },
  { type: "wgs84", lng: 114.21016180538568, lat: 22.219570659901557 },
) === true;