@heycar/heycars-map 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +6 -2
  2. package/dist/business-components/AddressBox/AddressBox.d.ts +1 -0
  3. package/dist/business-components/DrivingRoute/DrivingRoute.d.ts +5 -5
  4. package/dist/components/Amap/Amap.d.ts +3 -1
  5. package/dist/components/MapProvider/MapProvider.d.ts +1 -0
  6. package/dist/hooks/useGeoLocation.d.ts +22 -0
  7. package/dist/hooks/useMapAngle.d.ts +8 -9
  8. package/dist/hooks/useMapDrag.d.ts +10 -23
  9. package/dist/hooks/useMapPlace.d.ts +23 -0
  10. package/dist/hooks/useMapReady.d.ts +4 -0
  11. package/dist/hooks/useMapRecomendPlace.d.ts +27 -0
  12. package/dist/hooks-business/useBusinessMapRecomendPlace.d.ts +22 -0
  13. package/dist/index.cjs +48 -48
  14. package/dist/index.d.ts +4 -1
  15. package/dist/index.js +875 -710
  16. package/dist/style.css +1 -1
  17. package/dist/types/interface.d.ts +5 -0
  18. package/dist/utils/transform.d.ts +4 -0
  19. package/package.json +1 -1
  20. package/src/business-components/AddressBox/AddressBox.tsx +9 -3
  21. package/src/business-components/DrivingLine/DrivingLine.tsx +1 -0
  22. package/src/business-components/DrivingRoute/DrivingRoute.tsx +20 -15
  23. package/src/components/Amap/Amap.ts +15 -3
  24. package/src/components/AmapLoader/AmapLoader.ts +1 -1
  25. package/src/components/Demo/HeycarDemo.tsx +32 -8
  26. package/src/components/MapProvider/MapProvider.tsx +6 -2
  27. package/src/hooks/useDrivingRoute.ts +24 -22
  28. package/src/hooks/useGeoLocation.ts +44 -0
  29. package/src/hooks/useMapAngle.ts +12 -13
  30. package/src/hooks/useMapDrag.ts +30 -44
  31. package/src/hooks/useMapPlace.ts +66 -0
  32. package/src/hooks/useMapReady.ts +14 -0
  33. package/src/hooks/useMapRecomendPlace.ts +78 -0
  34. package/src/hooks-business/useBusinessMapRecomendPlace.ts +72 -0
  35. package/src/index.ts +4 -1
  36. package/src/types/interface.ts +5 -0
  37. package/src/utils/transform.ts +14 -0
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- ._15rq2xn0{display:flex;flex-direction:column;align-items:center;margin-bottom:-1.6vw}._15rq2xn1{padding:2.13vw 4.5vw 2.67vw 4.27vw;display:flex;align-items:center;background:linear-gradient(90deg,#79AFFF 0%,#5C8DFF 32%,#507FFF 75%,#4471FF 100%);border-radius:3.2vw}._15rq2xn2{font-size:3.47vw;font-family:PingFangSC-Semibold,PingFang SC;font-weight:600;color:#fff;line-height:4.8vw;white-space:nowrap}._15rq2xn3{font-size:2.93vw;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;color:#eafaf8;line-height:4.27vw;white-space:nowrap;opacity:.8}._15rq2xn4{margin-left:3.2vw;width:1.44vw;height:2.4vw}._15rq2xn5{width:.8vw;height:4vw;background:#4C80FF;border-radius:0vw 0vw 26.67vw 26.67vw;z-index:1}._15rq2xn6{margin-top:-1.5vw;width:3.2vw;height:3.2vw}.rgf09w0{width:7.1045vw;height:10.93vw;display:flex}._1l6offo0{display:flex;margin-bottom:-8.135vw;width:16.27vw;height:16.27vw}.fhyw80{display:flex;align-items:center}.fhyw81{flex-direction:row-reverse}.fhyw83{margin-right:-2.265vw}.fhyw84{margin-left:-2.265vw}.fhyw85{margin-bottom:-2.265vw}.fhyw86{margin-right:calc(50% - 2.265vw)}.fhyw87{margin-left:calc(50% - 2.265vw)}.fhyw88{display:flex;width:4.53vw;height:4.53vw}.fhyw89{font-size:3.47vw;font-family:PingFangSC-Semibold,PingFang SC;font-weight:600;color:#243e66;line-height:4.53vw;white-space:nowrap}._4a4ovk0{margin-bottom:-.4vw;display:flex;flex-direction:column;align-items:center}._4a4ovk1{padding:1.07vw 2.4vw 1.6vw 2.67vw;background:#FFFFFF;box-shadow:0 .53vw 2.4vw #3f3f3f33;border-radius:2.13vw}._4a4ovk2{padding:2.67vw 2.67vw 2.4vw 3.2vw;background:#FFFFFF;box-shadow:0 0 2.67vw #4e556c26;border-radius:4.8vw;font-size:3.2vw;font-family:PingFangSC-Medium,PingFang SC;font-weight:500;color:#1e1e1e;line-height:4.53vw;white-space:nowrap}._4a4ovk3{font-size:3.2vw;font-family:PingFangSC-Medium,PingFang SC;font-weight:500;color:#1e1e1e;line-height:4.53vw;white-space:nowrap}._4a4ovk4{font-size:2.4vw;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;color:#7e7e7e;line-height:3.47vw;white-space:nowrap}._4a4ovk5{color:#4471ff;font-family:PingFangSC-Medium,PingFang SC;font-weight:500}._4a4ovk6{margin-top:1.33vw;width:6.192vw;height:7.998vw}._4a4ovk7{margin-top:2.4vw;width:6.192vw;height:7.998vw}._65j3sr1{margin-top:1.87vw;margin-bottom:-5.5vw;width:6vw;height:11vw}@keyframes rrvp0y0{0%{transform:scale(0);opacity:1}33.33%{transform:scale(.5);opacity:1}66.66%{transform:scale(1);opacity:0}to{transform:scale(1);opacity:0}}@keyframes rrvp0y1{0%{transform:scale(0);opacity:0}33.33%{transform:scale(0);opacity:1}66.66%{transform:scale(.5);opacity:1}to{transform:scale(1);opacity:0}}.rrvp0y2{display:flex;margin-bottom:-30.935vw;width:61.87vw;height:61.87vw;animation-name:rrvp0y0;animation-duration:3s;animation-iteration-count:infinite;animation-timing-function:linear}.rrvp0y3{animation-name:rrvp0y1}
1
+ .rgf09w0{width:7.1045vw;height:10.93vw;display:flex}._15rq2xn0{display:flex;flex-direction:column;align-items:center;margin-bottom:-1.6vw}._15rq2xn1{padding:2.13vw 4.5vw 2.67vw 4.27vw;display:flex;align-items:center;background:linear-gradient(90deg,#79AFFF 0%,#5C8DFF 32%,#507FFF 75%,#4471FF 100%);border-radius:3.2vw}._15rq2xn2{font-size:3.47vw;font-family:PingFangSC-Semibold,PingFang SC;font-weight:600;color:#fff;line-height:4.8vw;white-space:nowrap}._15rq2xn3{font-size:2.93vw;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;color:#eafaf8;line-height:4.27vw;white-space:nowrap;opacity:.8}._15rq2xn4{margin-left:3.2vw;width:1.44vw;height:2.4vw}._15rq2xn5{width:.8vw;height:4vw;background:#4C80FF;border-radius:0vw 0vw 26.67vw 26.67vw;z-index:1}._15rq2xn6{margin-top:-1.5vw;width:3.2vw;height:3.2vw}._1l6offo0{display:flex;margin-bottom:-8.135vw;width:16.27vw;height:16.27vw}.fhyw80{display:flex;align-items:center}.fhyw81{flex-direction:row-reverse}.fhyw83{margin-right:-2.265vw}.fhyw84{margin-left:-2.265vw}.fhyw85{margin-bottom:-2.265vw}.fhyw86{margin-right:calc(50% - 2.265vw)}.fhyw87{margin-left:calc(50% - 2.265vw)}.fhyw88{display:flex;width:4.53vw;height:4.53vw}.fhyw89{font-size:3.47vw;font-family:PingFangSC-Semibold,PingFang SC;font-weight:600;color:#243e66;line-height:4.53vw;white-space:nowrap}._4a4ovk0{margin-bottom:-.4vw;display:flex;flex-direction:column;align-items:center}._4a4ovk1{padding:1.07vw 2.4vw 1.6vw 2.67vw;background:#FFFFFF;box-shadow:0 .53vw 2.4vw #3f3f3f33;border-radius:2.13vw}._4a4ovk2{padding:2.67vw 2.67vw 2.4vw 3.2vw;background:#FFFFFF;box-shadow:0 0 2.67vw #4e556c26;border-radius:4.8vw;font-size:3.2vw;font-family:PingFangSC-Medium,PingFang SC;font-weight:500;color:#1e1e1e;line-height:4.53vw;white-space:nowrap}._4a4ovk3{font-size:3.2vw;font-family:PingFangSC-Medium,PingFang SC;font-weight:500;color:#1e1e1e;line-height:4.53vw;white-space:nowrap}._4a4ovk4{font-size:2.4vw;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;color:#7e7e7e;line-height:3.47vw;white-space:nowrap}._4a4ovk5{color:#4471ff;font-family:PingFangSC-Medium,PingFang SC;font-weight:500}._4a4ovk6{margin-top:1.33vw;width:6.192vw;height:7.998vw}._4a4ovk7{margin-top:2.4vw;width:6.192vw;height:7.998vw}._65j3sr1{margin-top:1.87vw;margin-bottom:-5.5vw;width:6vw;height:11vw}@keyframes rrvp0y0{0%{transform:scale(0);opacity:1}33.33%{transform:scale(.5);opacity:1}66.66%{transform:scale(1);opacity:0}to{transform:scale(1);opacity:0}}@keyframes rrvp0y1{0%{transform:scale(0);opacity:0}33.33%{transform:scale(0);opacity:1}66.66%{transform:scale(.5);opacity:1}to{transform:scale(1);opacity:0}}.rrvp0y2{display:flex;margin-bottom:-30.935vw;width:61.87vw;height:61.87vw;animation-name:rrvp0y0;animation-duration:3s;animation-iteration-count:infinite;animation-timing-function:linear}.rrvp0y3{animation-name:rrvp0y1}
@@ -2,3 +2,8 @@
2
2
  import type { ShallowRef } from "vue-demi";
3
3
  export type Point = [number, number];
4
4
  export type MapShallowRef<M = AMap.Map | google.maps.Map> = ShallowRef<M | undefined>;
5
+ export type Place = {
6
+ lng: number;
7
+ lat: number;
8
+ name: string;
9
+ };
@@ -1,4 +1,5 @@
1
1
  /// <reference types="google.maps" />
2
+ import type { Place, Point } from "../types/interface";
2
3
  export declare const vec2lnglat: ([lng, lat]: [number, number]) => google.maps.LatLngLiteral;
3
4
  export interface AsteriskItem {
4
5
  type: "normal" | "emphasize";
@@ -7,3 +8,6 @@ export interface AsteriskItem {
7
8
  export declare const decodeAsterisk: (encodedValue: string) => AsteriskItem[];
8
9
  export declare const property2emitEventName: (propertyName: string) => string;
9
10
  export declare const property2mapEventName: (propertyName: string) => string;
11
+ export type VectorMapForeign = "style_en" | "style_local" | "style_zh_cn";
12
+ export declare const language2vectorMapForeign: (lang: "en" | "zh") => VectorMapForeign;
13
+ export declare const place2point: (place: Place) => Point;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heycar/heycars-map",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite -c vite.config.dev.ts",
@@ -8,9 +8,11 @@ import { createElement, defineSetup } from "../../types/helper";
8
8
  import type { Point } from "../../types/interface";
9
9
  import { createDom } from "../../utils/dom";
10
10
  import { vec2lnglat } from "../../utils/transform";
11
+ import { AAddressLocator, GAddressLocator } from "../AddressLocator";
11
12
  import * as css from "./AddressBox.css";
12
13
 
13
14
  interface AddressBoxProps {
15
+ type: "box" | "locator";
14
16
  position: Point;
15
17
  title: string;
16
18
  description?: string;
@@ -31,9 +33,12 @@ export const AAddressBox = defineSetup(function AAddressBox(props: AddressBoxPro
31
33
  </div>
32
34
  `
33
35
  );
34
- return () => (
35
- <AmapMarker position={props.position} content={contentRef.value} anchor={"bottom-center"} />
36
- );
36
+ return () => {
37
+ if (props.type === "locator") return <AAddressLocator position={props.position} />;
38
+ return (
39
+ <AmapMarker position={props.position} content={contentRef.value} anchor={"bottom-center"} />
40
+ );
41
+ };
37
42
  });
38
43
 
39
44
  export const GAddressBox = defineSetup(function GAddressBox(props: AddressBoxProps) {
@@ -55,6 +60,7 @@ export const GAddressBox = defineSetup(function GAddressBox(props: AddressBoxPro
55
60
  )
56
61
  );
57
62
  return () => {
63
+ if (props.type === "locator") return <GAddressLocator position={props.position} />;
58
64
  return (
59
65
  <GmapAdvancedMarkerView position={vec2lnglat(props.position)} content={contentRef.value} />
60
66
  );
@@ -124,6 +124,7 @@ export const GDrivingLine = defineSetup(function GDrivingLine(props: DrivingLine
124
124
  export const DrivingLine = defineSetup(function DrivingLine(props: DrivingLineProps) {
125
125
  const payload = useMapSupplier();
126
126
  return () => {
127
+ if (!props.path.length) return null;
127
128
  return createElement(payload.supplier === "gmap" ? GDrivingLine : ADrivingLine, {
128
129
  attrs: props,
129
130
  });
@@ -1,4 +1,4 @@
1
- import type { Ref, ShallowRef } from "vue-demi";
1
+ import { reactive, VNodeData } from "vue-demi";
2
2
  import { useAmap } from "../../components/Amap/useAmap";
3
3
  import { useGmap } from "../../components/Gmap/useGmap";
4
4
  import { useMapSupplier } from "../../components/MapProvider/useMapSupplier";
@@ -11,33 +11,38 @@ import { useAmapAngle, useGmapAngle } from "../../hooks/useMapAngle";
11
11
  import { createElement, defineSetup, VNodeChild } from "../../types/helper";
12
12
  import type { Point } from "../../types/interface";
13
13
 
14
+ export type DrivingRouteRenderProps = {
15
+ path: Point[];
16
+ angle?: number;
17
+ };
14
18
  export interface DrivingRouteProps extends UseDrivingRouteProps {
15
- render?: (props: {
16
- pathRef: ShallowRef<Point[]>;
17
- angleRef: Ref<number | undefined>;
18
- }) => VNodeChild;
19
+ render?: (props: DrivingRouteRenderProps) => VNodeChild;
19
20
  }
20
21
  export const ADrivingRoute = defineSetup(function DrivingRoute(
21
22
  props: DrivingRouteProps,
22
23
  { slots }
23
24
  ) {
24
- const mapRef = useAmap();
25
- const pathRef = useADrivingRoute(props);
26
- const angleRef = useAmapAngle({ pathRef, mapRef });
27
- return () => <div>{slots.render?.({ pathRef, angleRef })}</div>;
25
+ const map = useAmap();
26
+ const path = useADrivingRoute(props);
27
+ const angle = useAmapAngle(reactive({ path, map }));
28
+ return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
28
29
  });
29
30
 
30
31
  export const GDrivingRoute = defineSetup(function DrivingRoute(
31
32
  props: DrivingRouteProps,
32
33
  { slots }
33
34
  ) {
34
- const mapRef = useGmap();
35
- const pathRef = useGDrivingRoute(props);
36
- const angleRef = useGmapAngle({ pathRef, mapRef });
37
- return () => <div>{slots.render?.({ pathRef, angleRef })}</div>;
35
+ const map = useGmap();
36
+ const path = useGDrivingRoute(props);
37
+ const angle = useGmapAngle(reactive({ path, map }));
38
+ return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
38
39
  });
39
40
 
40
- export const DrivingRoute = defineSetup(function DrivingRoute(props: DrivingRouteProps) {
41
+ export const DrivingRoute = defineSetup(function DrivingRoute(props: DrivingRouteProps, { slots }) {
41
42
  const { supplier } = useMapSupplier();
42
- return () => createElement(supplier === "gmap" ? GDrivingRoute : ADrivingRoute, { attrs: props });
43
+ return () =>
44
+ createElement(supplier === "gmap" ? GDrivingRoute : ADrivingRoute, {
45
+ attrs: props,
46
+ scopedSlots: slots as VNodeData["scopedSlots"],
47
+ });
43
48
  });
@@ -7,17 +7,25 @@ import {
7
7
  watchNoneImmediatePostEffectForMapProperty,
8
8
  watchPostEffectForAMapEvent,
9
9
  } from "../../utils/compare";
10
+ import type { VectorMapForeign } from "../../utils/transform";
10
11
  import * as css from "./Amap.css";
11
12
  import { provideAmap } from "./useAmap";
12
13
 
13
- export interface AmapProps extends AMap.MapOptions {
14
+ export interface AmapProps extends Omit<AMap.MapOptions, "vectorMapForeign"> {
15
+ vectorMapForeign?: VectorMapForeign;
14
16
  mapRef?: SetMap<AMap.Map>;
15
17
  onDragStart?: MapEventHandler<AMap.Map>;
16
18
  onDragEnd?: MapEventHandler<AMap.Map>;
17
19
  }
18
20
 
19
21
  export const Amap = defineSetup(function Amap(props: AmapProps, { slots, emit }) {
20
- const { onDragStart, onDragEnd, mapRef: setMap, ...defaultOptions } = props;
22
+ const {
23
+ onDragStart,
24
+ onDragEnd,
25
+ mapRef: setMap,
26
+ vectorMapForeign = "style_zh_cn",
27
+ ...defaultOptions
28
+ } = props;
21
29
  const statusOptions = computed(() => {
22
30
  return {
23
31
  dragEnable: !!props.dragEnable,
@@ -35,7 +43,11 @@ export const Amap = defineSetup(function Amap(props: AmapProps, { slots, emit })
35
43
  watchPostEffect(() => {
36
44
  // todo 这里是否会因为 mapRef 的赋值导致不停运行?
37
45
  if (mapRef.value || !elementRef.value) return;
38
- const map = new AMap.Map(elementRef.value, { ...defaultOptions });
46
+ const map = new AMap.Map(elementRef.value, {
47
+ ...defaultOptions,
48
+ vectorMapForeign: vectorMapForeign as any,
49
+ mapStyle: "amap://styles/95498a904992a4c0b866a3e4d7729682",
50
+ });
39
51
  mapRef.value = map;
40
52
  setMap?.(map);
41
53
  });
@@ -29,7 +29,7 @@ export const AmapLoader = defineSetup(function AmapLoader(props: AmapLoaderProps
29
29
  const optionsRef = computed(() => {
30
30
  const { onChange, loading, fallback, apiKey, apiSecret, apiServiceHost, version, ...options } =
31
31
  props;
32
- return { ...options, key: apiKey, version: version ?? "2.0" };
32
+ return { ...options, key: apiKey, version: version ?? "2.0.5.16" };
33
33
  });
34
34
  watchPostEffectForDeepOption(
35
35
  () => optionsRef.value,
@@ -1,8 +1,12 @@
1
+ import { AddressBox } from "../../business-components/AddressBox";
1
2
  import { DrivingLine } from "../../business-components/DrivingLine";
2
3
  import { DrivingRoute } from "../../business-components/DrivingRoute";
3
4
  import { TaxiCar } from "../../business-components/TaxiCar";
5
+ import {
6
+ useBusinessMapRecomendPlace,
7
+ UseBusinessMapRecomendPlaceProps,
8
+ } from "../../hooks-business/useBusinessMapRecomendPlace";
4
9
  import { useHeycarMap } from "../../hooks/useHeycarMap";
5
- import { useMapDrag } from "../../hooks/useMapDrag";
6
10
  import { defineSetup } from "../../types/helper";
7
11
  import { HeycarMap, MapProvider } from "../MapProvider/MapProvider";
8
12
  import * as css from "./Demo.css";
@@ -28,22 +32,42 @@ export const HeycarDemo = defineSetup(function HeycarDemo() {
28
32
 
29
33
  export const SomePage = defineSetup(function Hello() {
30
34
  const { mapRef, setMap, panTo } = useHeycarMap();
31
- const { centerPlace, isDragging } = useMapDrag(mapRef);
35
+ const getRecomendPlace: UseBusinessMapRecomendPlaceProps["getRecomendPlace"] = async (place) => {
36
+ const { lat, lng } = place;
37
+ console.log("typeof lat = ", typeof lat);
38
+ return [{ lat: lat + 0.0001, lng: lng + 0.0001, name: "place name 1" }];
39
+ };
40
+ const { centerPlace, centerPoint, isDragging, isGeoLoading, geoError } =
41
+ useBusinessMapRecomendPlace({
42
+ mapRef,
43
+ recomendPlaceGeoLimit: 300,
44
+ recomendPlaceDragLimit: 30,
45
+ getRecomendPlace,
46
+ onChangeGeoLocation: (v) => console.log("onChangeGeoLocation: ", v),
47
+ onChangePlace: (v) => console.log("onChangePlace: ", v),
48
+ onChangeRecomandPlace: (v) => console.log("onChangeRecomandPlace: ", v),
49
+ });
32
50
  (window as any).panTo = panTo;
33
51
  return () => {
34
52
  return (
35
53
  <div>
54
+ isGeoLoading: {`${isGeoLoading.value}`} <br />
36
55
  isDragging: {`${isDragging.value}`} <br />
37
- {centerPlace.lng} | {centerPlace.lat} | {centerPlace.name}
56
+ {centerPlace.lng} | {centerPlace.lat} | {centerPlace.name} <br />
38
57
  <HeycarMap
39
58
  class={css.demo}
40
59
  fallback={() => <div>error</div>}
41
60
  loading={() => <div>loading</div>}
42
- center={[121, 31]}
61
+ center={[centerPlace.lng, centerPlace.lat]}
43
62
  zoom={15}
44
63
  mapRef={setMap}
45
64
  >
46
- {/* <AddressBox position={[0, 0]} title={"Martyrs Lawn"} description={"您将在此处上车"} /> */}
65
+ <AddressBox
66
+ type="box"
67
+ position={centerPoint.value}
68
+ title={"Martyrs Lawn"}
69
+ description={"您将在此处上车"}
70
+ />
47
71
  {/* <TaxiCar position={[121, 31]} angle={0} /> */}
48
72
  {/* <PickupPoints
49
73
  positions={[
@@ -55,9 +79,9 @@ export const SomePage = defineSetup(function Hello() {
55
79
  <DrivingRoute
56
80
  from={[121, 31]}
57
81
  to={[121.6, 31.3]}
58
- render={({ pathRef, angleRef }) => [
59
- pathRef.value.length > 0 && <DrivingLine path={pathRef.value} />,
60
- <TaxiCar position={[121, 31]} angle={angleRef.value} />,
82
+ render={({ path, angle }) => [
83
+ <DrivingLine path={path} />,
84
+ <TaxiCar position={[121, 31]} angle={angle} />,
61
85
  ]}
62
86
  />
63
87
  </HeycarMap>
@@ -1,6 +1,6 @@
1
1
  import type { SetMap } from "../../hooks/useHeycarMap";
2
2
  import { defineLagecySetup } from "../../types/helper";
3
- import { vec2lnglat } from "../../utils/transform";
3
+ import { language2vectorMapForeign, vec2lnglat } from "../../utils/transform";
4
4
  import { Amap, AmapProps } from "../Amap";
5
5
  import { AmapLoader } from "../AmapLoader";
6
6
  import { Gmap, GmapProps } from "../Gmap";
@@ -19,6 +19,7 @@ export const MapProvider = defineLagecySetup(function MapProvider(
19
19
  export interface HeycarMapProps
20
20
  extends Pick<GmapLoaderProps, "fallback" | "loading">,
21
21
  Pick<AmapProps, "center" | "zoom"> {
22
+ language?: "en" | "zh";
22
23
  mapRef?: SetMap<AMap.Map> | SetMap<google.maps.Map>;
23
24
  onDragEnd?: (value: [number, number]) => any;
24
25
  }
@@ -37,13 +38,15 @@ export const HeycarMap = defineLagecySetup(function HeycarMap(
37
38
  };
38
39
  return () => {
39
40
  const { gmapKey, amapKey, amapSecret, amapServiceHost, supplier, gmapId } = payload;
40
- const { mapRef: setMap, fallback, loading, center, zoom } = props;
41
+ const { mapRef: setMap, center, zoom, language = "zh" } = props;
42
+ const { fallback, loading } = slots;
41
43
  const children = slots.default?.();
42
44
  switch (supplier) {
43
45
  case "gmap":
44
46
  return (
45
47
  <GmapLoader
46
48
  apiKey={gmapKey}
49
+ language={language}
47
50
  version="beta"
48
51
  libraries={["marker", "places", "geometry"]}
49
52
  loading={loading}
@@ -78,6 +81,7 @@ export const HeycarMap = defineLagecySetup(function HeycarMap(
78
81
  >
79
82
  <Amap
80
83
  mapRef={setMap as SetMap<AMap.Map>}
84
+ vectorMapForeign={language2vectorMapForeign(language)}
81
85
  center={center}
82
86
  zoom={zoom}
83
87
  onDragEnd={amapDebounceEmit}
@@ -1,6 +1,7 @@
1
- import { ShallowRef, shallowRef, watch } from "vue-demi";
1
+ import { ShallowRef, shallowRef } from "vue-demi";
2
2
  import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
3
3
  import type { Point } from "../types/interface";
4
+ import { watchPostEffectForDeepOption } from "../utils/compare";
4
5
 
5
6
  export interface UseDrivingRouteProps {
6
7
  from: Point;
@@ -10,15 +11,14 @@ export interface UseDrivingRouteProps {
10
11
  export const useADrivingRoute = (props: UseDrivingRouteProps) => {
11
12
  const pathRef = shallowRef<Point[]>([]);
12
13
  const amapDriving = new AMap.Driving({});
13
- watch(
14
- [() => props.from, () => props.to],
15
- ([from, to]) => {
14
+ watchPostEffectForDeepOption(
15
+ () => ({ ...props }),
16
+ ({ from, to }) => {
16
17
  amapDriving.search(
17
18
  AMap.LngLat.from(from),
18
19
  AMap.LngLat.from(to),
19
20
  { waypoints: [] },
20
21
  (status, result) => {
21
- console.log("result = ", result);
22
22
  switch (status) {
23
23
  case "complete": {
24
24
  let path: Point[] = [];
@@ -40,8 +40,7 @@ export const useADrivingRoute = (props: UseDrivingRouteProps) => {
40
40
  }
41
41
  }
42
42
  );
43
- },
44
- { immediate: true }
43
+ }
45
44
  );
46
45
  return pathRef;
47
46
  };
@@ -49,22 +48,25 @@ export const useADrivingRoute = (props: UseDrivingRouteProps) => {
49
48
  export const useGDrivingRoute = (props: UseDrivingRouteProps) => {
50
49
  const pathRef = shallowRef<Point[]>([]);
51
50
  const gmapDirectionsService = new google.maps.DirectionsService();
52
- watch([() => props.from, () => props.to], ([from, to]) => {
53
- gmapDirectionsService
54
- .route({
55
- origin: { lng: from[0], lat: from[1] },
56
- destination: { lng: to[0], lat: to[1] },
57
- travelMode: google.maps.TravelMode.WALKING,
58
- })
59
- .then((result) => {
60
- let path: Point[] = [];
61
- result.routes.map((route) => {
62
- const stepPath = route.overview_path.map<Point>((item) => [item.lng(), item.lat()]);
63
- path = path.concat(stepPath);
51
+ watchPostEffectForDeepOption(
52
+ () => ({ ...props }),
53
+ ({ from, to }) => {
54
+ gmapDirectionsService
55
+ .route({
56
+ origin: { lng: from[0], lat: from[1] },
57
+ destination: { lng: to[0], lat: to[1] },
58
+ travelMode: google.maps.TravelMode.WALKING,
59
+ })
60
+ .then((result) => {
61
+ let path: Point[] = [];
62
+ result.routes.map((route) => {
63
+ const stepPath = route.overview_path.map<Point>((item) => [item.lng(), item.lat()]);
64
+ path = path.concat(stepPath);
65
+ });
66
+ pathRef.value = path;
64
67
  });
65
- pathRef.value = path;
66
- });
67
- });
68
+ }
69
+ );
68
70
  return pathRef;
69
71
  };
70
72
 
@@ -0,0 +1,44 @@
1
+ import { ref, watchEffect } from "vue-demi";
2
+ import type { MapShallowRef, Point } from "../types/interface";
3
+
4
+ export interface UseGeoLocationProps {
5
+ mapRef: MapShallowRef;
6
+ onChange?: (value: { position: Point; coordinate: GeolocationCoordinates }) => any;
7
+ }
8
+ export const useGeoLocation = (props: UseGeoLocationProps) => {
9
+ const { mapRef, onChange } = props;
10
+ const loading = ref(false);
11
+ const errorRef = ref<GeolocationPositionError>();
12
+ const coordinateRef = ref<GeolocationCoordinates>({
13
+ accuracy: 0,
14
+ altitude: 0,
15
+ altitudeAccuracy: 0,
16
+ heading: 0,
17
+ latitude: 0,
18
+ longitude: 0,
19
+ speed: 0,
20
+ });
21
+ const positionRef = ref<Point>([coordinateRef.value.longitude, coordinateRef.value.latitude]);
22
+ watchEffect(() => {
23
+ mapRef.value;
24
+ loading.value = true;
25
+ navigator.geolocation.getCurrentPosition(
26
+ (position) => {
27
+ loading.value = false;
28
+ const coordinate = position.coords;
29
+ const point: Point = [position.coords.longitude, position.coords.latitude];
30
+ coordinateRef.value = coordinate;
31
+ positionRef.value = point;
32
+ onChange?.({ position: point, coordinate });
33
+ },
34
+ (error) => {
35
+ loading.value = false;
36
+ errorRef.value = error;
37
+ console.log("errorRef = ", errorRef);
38
+ },
39
+
40
+ { timeout: 5000 }
41
+ );
42
+ });
43
+ return { errorRef, positionRef, coordinateRef, loading };
44
+ };
@@ -1,35 +1,34 @@
1
- import { computed, ShallowRef } from "vue";
1
+ import { computed } from "vue-demi";
2
2
  import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
3
- import type { MapShallowRef, Point } from "../types/interface";
3
+ import type { Point } from "../types/interface";
4
4
  import { vec2lnglat } from "../utils/transform";
5
5
 
6
6
  const amapComputeHeading = (from: Point, to: Point, map?: AMap.Map) => {
7
7
  if (!map) return 0;
8
8
  const { x: xFrom, y: yFrom } = map.lngLatToContainer(from);
9
9
  const { x: xTo, y: yTo } = map.lngLatToContainer(to);
10
- console.log("yTo - yFrom, xTo - xFrom = ", yTo - yFrom, xTo - xFrom);
11
10
  const theta = Math.atan2(yFrom - yTo, xTo - xFrom);
12
11
  return ((Math.PI / 2 - theta) / Math.PI) * 180;
13
12
  };
14
13
 
15
- export interface UseMapAngleProps<T = AMap.Map | google.maps.Map> {
16
- pathRef: ShallowRef<Point[]>;
17
- mapRef?: MapShallowRef<T>;
18
- }
14
+ export type UseMapAngleProps<M = AMap.Map | google.maps.Map> = {
15
+ path: Point[];
16
+ map?: M;
17
+ };
19
18
 
20
19
  export const useAmapAngle = (props: UseMapAngleProps<AMap.Map>) => {
21
20
  return computed(() => {
22
- const { mapRef, pathRef } = props;
23
- const [from, to] = pathRef.value;
24
- if (!from || !to || !mapRef) return undefined;
25
- return amapComputeHeading(from, to, mapRef.value);
21
+ const { map, path } = props;
22
+ const [from, to] = path;
23
+ if (!from || !to || !map) return undefined;
24
+ return amapComputeHeading(from, to, map);
26
25
  });
27
26
  };
28
27
 
29
28
  export const useGmapAngle = (props: UseMapAngleProps<google.maps.Map>) => {
30
29
  return computed(() => {
31
- const { pathRef } = props;
32
- const [from, to] = pathRef.value;
30
+ const { path } = props;
31
+ const [from, to] = path;
33
32
  if (!from || !to) return undefined;
34
33
  return google.maps.geometry.spherical.computeHeading(vec2lnglat(from), vec2lnglat(to));
35
34
  });
@@ -1,81 +1,67 @@
1
- import { reactive, ref, type ShallowRef } from "vue-demi";
1
+ import { ref, type ShallowRef } from "vue-demi";
2
2
  import type { AmapProps } from "../components/Amap";
3
3
  import type { GmapProps } from "../components/Gmap";
4
4
  import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
5
- import { LANGUAGE, SetupContextEmitHandler } from "../types/helper";
6
- import type { MapShallowRef } from "../types/interface";
5
+ import type { SetupContextEmitHandler } from "../types/helper";
6
+ import type { Point } from "../types/interface";
7
7
  import { watchPostEffectForAMapEvent, watchPostEffectForGMapEvent } from "../utils/compare";
8
8
 
9
9
  export const ON_CHANGE_CENTER_INTERVAL = 200;
10
- export interface UseMapCenterPlace {
11
- lng: number;
12
- lat: number;
13
- name: string;
10
+
11
+ export interface UseMapDragProps<M = AMap.Map | google.maps.Map> {
12
+ mapRef: ShallowRef<M | undefined>;
13
+ onChange?: (value: Point) => any;
14
14
  }
15
- export const useAmapDrag = (amapRef: ShallowRef<AMap.Map | undefined>) => {
16
- const centerPlace = reactive<UseMapCenterPlace>({ lng: 0, lat: 0, name: "" });
15
+ export const useAmapDrag = (props: UseMapDragProps<AMap.Map>) => {
16
+ const { mapRef, onChange } = props;
17
+ const centerRef = ref<Point>([0, 0]);
17
18
  const isDragging = ref(false);
18
19
  const emitDragStart: SetupContextEmitHandler<Pick<AmapProps, "onDragStart">> = () => {
19
20
  Promise.resolve().then(() => (isDragging.value = true));
20
21
  };
21
22
  const emitDragEnd: SetupContextEmitHandler<Pick<AmapProps, "onDragEnd">> = (_, { target }) => {
22
23
  isDragging.value = false;
23
- const center = target.getCenter();
24
- centerPlace.lng = center.lng;
25
- centerPlace.lat = center.lat;
26
- const geocoder = new AMap.Geocoder({ lang: LANGUAGE });
27
- geocoder.getAddress(center, (status, result) => {
28
- switch (status) {
29
- case "complete":
30
- centerPlace.name = (result as AMap.ReGeocoderResult).regeocode.formattedAddress;
31
- return;
32
- case "no_data":
33
- return;
34
- case "error":
35
- throw result;
36
- }
37
- });
24
+ const { lng, lat } = target.getCenter();
25
+ centerRef.value = [lng, lat];
26
+ onChange?.([lng, lat]);
38
27
  };
39
- watchPostEffectForAMapEvent(amapRef, {} as Pick<AmapProps, "onDragStart">, emitDragStart, [
28
+ watchPostEffectForAMapEvent(mapRef, {} as Pick<AmapProps, "onDragStart">, emitDragStart, [
40
29
  "onDragStart",
41
30
  ]);
42
- watchPostEffectForAMapEvent(amapRef, {} as Pick<AmapProps, "onDragEnd">, emitDragEnd, [
31
+ watchPostEffectForAMapEvent(mapRef, {} as Pick<AmapProps, "onDragEnd">, emitDragEnd, [
43
32
  "onDragEnd",
44
33
  ]);
45
- return { centerPlace, isDragging };
34
+ return { centerRef, isDragging };
46
35
  };
47
36
 
48
- export const useGmapDrag = (gmapRef: ShallowRef<google.maps.Map | undefined>) => {
49
- const centerPlace = reactive<UseMapCenterPlace>({ lng: 0, lat: 0, name: "" });
37
+ export const useGmapDrag = (props: UseMapDragProps<google.maps.Map>) => {
38
+ const { mapRef, onChange } = props;
39
+ const centerRef = ref<Point>([0, 0]);
50
40
  const isDragging = ref(false);
51
41
  const emitDragStart: SetupContextEmitHandler<Pick<GmapProps, "onDragStart">> = () => {
52
42
  Promise.resolve().then(() => (isDragging.value = true));
53
43
  };
54
44
  const emitDragEnd: SetupContextEmitHandler<Pick<GmapProps, "onDragEnd">> = async () => {
55
45
  isDragging.value = false;
56
- const center = gmapRef.value?.getCenter();
57
- if (!center) return;
58
- const lng = center?.lng();
59
- const lat = center?.lat();
60
- if (lng) centerPlace.lng = lng;
61
- if (lat) centerPlace.lat = lat;
62
- const geocoder = new google.maps.Geocoder();
63
- const { results } = await geocoder.geocode({ language: LANGUAGE, location: center });
64
- centerPlace.name = results[0].formatted_address;
46
+ const center = mapRef.value?.getCenter();
47
+ const lng = center?.lng() as number;
48
+ const lat = center?.lat() as number;
49
+ centerRef.value = [lng, lat];
50
+ onChange?.([lng, lat]);
65
51
  };
66
- watchPostEffectForGMapEvent(gmapRef!, {} as Pick<GmapProps, "onDragStart">, emitDragStart, [
52
+ watchPostEffectForGMapEvent(mapRef!, {} as Pick<GmapProps, "onDragStart">, emitDragStart, [
67
53
  "onDragStart",
68
54
  ]);
69
- watchPostEffectForGMapEvent(gmapRef!, {} as Pick<GmapProps, "onDragEnd">, emitDragEnd, [
55
+ watchPostEffectForGMapEvent(mapRef!, {} as Pick<GmapProps, "onDragEnd">, emitDragEnd, [
70
56
  "onDragEnd",
71
57
  ]);
72
- return { centerPlace, isDragging };
58
+ return { centerRef, isDragging };
73
59
  };
74
60
 
75
- export const useMapDrag = (mapRef: MapShallowRef) => {
61
+ export const useMapDrag = (props: UseMapDragProps) => {
76
62
  const { supplier } = useMapSupplier();
77
63
  // todo: 这里违反 react hook 规则,但 react 版本应该可以同时调用 useAmap 和 useGmap
78
64
  return supplier === "gmap"
79
- ? useGmapDrag(mapRef as ShallowRef<google.maps.Map | undefined>)
80
- : useAmapDrag(mapRef as ShallowRef<AMap.Map | undefined>);
65
+ ? useGmapDrag(props as UseMapDragProps<google.maps.Map>)
66
+ : useAmapDrag(props as UseMapDragProps<AMap.Map>);
81
67
  };