@heycar/heycars-map 0.1.4 → 0.1.6

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 (36) 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/hooks/useGeoLocation.d.ts +22 -0
  5. package/dist/hooks/useMapAngle.d.ts +8 -9
  6. package/dist/hooks/useMapDrag.d.ts +10 -23
  7. package/dist/hooks/useMapPlace.d.ts +32 -0
  8. package/dist/hooks/useMapReady.d.ts +4 -0
  9. package/dist/hooks/useMapRecomendPlace.d.ts +830 -0
  10. package/dist/hooks/useUdate.d.ts +4 -0
  11. package/dist/hooks-business/useBusinessMapRecomendPlace.d.ts +29 -0
  12. package/dist/index.cjs +56 -56
  13. package/dist/index.d.ts +4 -1
  14. package/dist/index.js +995 -809
  15. package/dist/style.css +1 -1
  16. package/dist/types/interface.d.ts +5 -0
  17. package/dist/utils/compare.d.ts +1 -0
  18. package/dist/utils/transform.d.ts +3 -0
  19. package/package.json +2 -2
  20. package/src/business-components/AddressBox/AddressBox.tsx +9 -3
  21. package/src/business-components/DrivingRoute/DrivingRoute.tsx +14 -14
  22. package/src/components/Demo/HeycarDemo.tsx +34 -8
  23. package/src/hooks/useDrivingRoute.ts +24 -21
  24. package/src/hooks/useGeoLocation.ts +53 -0
  25. package/src/hooks/useMapAngle.ts +12 -13
  26. package/src/hooks/useMapDrag.ts +31 -44
  27. package/src/hooks/useMapPlace.ts +82 -0
  28. package/src/hooks/useMapReady.ts +14 -0
  29. package/src/hooks/useMapRecomendPlace.ts +98 -0
  30. package/src/hooks/useUdate.ts +9 -0
  31. package/src/hooks-business/useBusinessMapRecomendPlace.ts +94 -0
  32. package/src/index.ts +4 -1
  33. package/src/types/interface.ts +5 -0
  34. package/src/utils/compare.ts +12 -0
  35. package/src/utils/transform.ts +10 -0
  36. package/todo.md +9 -0
@@ -0,0 +1,98 @@
1
+ import { reactive, Ref, watch } from "vue-demi";
2
+ import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
3
+ import type { MapShallowRef, Place, Point } from "../types/interface";
4
+ import { pipeAsync, place2point } from "../utils/transform";
5
+ import { useAmapPlace, useGmapPlace, UseMapPlaceProps } from "./useMapPlace";
6
+ import { useMapReady } from "./useMapReady";
7
+ import { useUpdate } from "./useUdate";
8
+
9
+ const findAmapNearestPlace = (place: Place, candidates: Place[]) => {
10
+ let shortestDistance = Infinity;
11
+ let shortestPlace = place;
12
+ for (const candidate of candidates) {
13
+ const distance = AMap.GeometryUtil.distance(place2point(place), place2point(candidate));
14
+ if (distance >= shortestDistance) continue;
15
+ shortestPlace = candidate;
16
+ shortestDistance = distance;
17
+ }
18
+ return { shortestPlace, shortestDistance };
19
+ };
20
+
21
+ const findGmapNearestPlace = (place: Place, candidates: Place[]) => {
22
+ let shortestDistance = Infinity;
23
+ let shortestPlace = place;
24
+ for (const candidate of candidates) {
25
+ const distance = google.maps.geometry.spherical.computeDistanceBetween(place, candidate);
26
+ if (distance >= shortestDistance) continue;
27
+ shortestPlace = candidate;
28
+ shortestDistance = distance;
29
+ }
30
+ return { shortestPlace, shortestDistance };
31
+ };
32
+
33
+ export interface UseMapRecomendPlaceProps<M = AMap.Map | google.maps.Map, C = Record<string, any>> {
34
+ mapRef: MapShallowRef<M>;
35
+ pointRef: Ref<Point>;
36
+ context?: C;
37
+ getLimit: (context?: C) => number;
38
+ getRecomendPlace: (place: Place, context?: C) => Promise<Place[]>;
39
+ onChangePlace?: UseMapPlaceProps["onChange"];
40
+ onChange?: (place: Place) => any;
41
+ }
42
+ export const useAmapRecomendPlace = <C>(props: UseMapRecomendPlaceProps<AMap.Map, C>) => {
43
+ const { pointRef, mapRef, getRecomendPlace, getLimit, context, onChange, onChangePlace } = props;
44
+ const { idx: recomendPlaceKey, update: updateRecomandPlace } = useUpdate();
45
+ const { readyRef } = useMapReady(mapRef);
46
+ const { place, updatePlace } = useAmapPlace({ pointRef, mapRef, onChange: onChangePlace });
47
+ const recomendPlace = reactive<Place>({ ...place });
48
+ watch(
49
+ () => recomendPlaceKey.value,
50
+ async () => {
51
+ debugger;
52
+ if (!readyRef.value) return;
53
+ const placeCandidates = await getRecomendPlace({ ...place }, context);
54
+ const { shortestPlace, shortestDistance } = findAmapNearestPlace(place, placeCandidates);
55
+ console.log("shortestPlace, shortestDistance = ", shortestPlace, shortestDistance);
56
+ const limit = getLimit(context);
57
+ const resultPlace = shortestDistance > limit ? place : shortestPlace;
58
+ Object.assign(recomendPlace, { ...resultPlace });
59
+ pipeAsync(onChange)?.({ ...resultPlace });
60
+ },
61
+ {
62
+ onTrigger(e) {
63
+ console.log("UseMapRecomendPlaceProps onTrigger: ", e.key, e.newValue, e.oldValue);
64
+ },
65
+ }
66
+ );
67
+ return { recomendPlace, updateRecomandPlace, updatePlace };
68
+ };
69
+
70
+ export const useGmapRecomendPlace = <C>(props: UseMapRecomendPlaceProps<google.maps.Map, C>) => {
71
+ const { pointRef, mapRef, getRecomendPlace, getLimit, context, onChange, onChangePlace } = props;
72
+ const { idx: recomendPlaceKey, update: updateRecomandPlace } = useUpdate();
73
+ const { readyRef } = useMapReady(mapRef);
74
+ const { place, updatePlace } = useGmapPlace({ pointRef, mapRef, onChange: onChangePlace });
75
+ const recomendPlace = reactive<Place>({ ...place });
76
+ watch(
77
+ () => recomendPlaceKey.value,
78
+ async () => {
79
+ if (!readyRef.value) return;
80
+ const placeCandidates = await getRecomendPlace({ ...place }, context);
81
+ const { shortestPlace, shortestDistance } = findGmapNearestPlace(place, placeCandidates);
82
+ const limit = getLimit(context);
83
+ const resultPlace = shortestDistance > limit ? place : shortestPlace;
84
+ Object.assign(recomendPlace, { ...resultPlace });
85
+ pipeAsync(onChange)?.({ ...resultPlace });
86
+ }
87
+ );
88
+ return { recomendPlace, updateRecomandPlace, updatePlace };
89
+ };
90
+
91
+ export const useMapRecomendPlace = <C>(
92
+ props: UseMapRecomendPlaceProps<AMap.Map | google.maps.Map, C>
93
+ ) => {
94
+ const { supplier } = useMapSupplier();
95
+ return supplier === "gmap"
96
+ ? useGmapRecomendPlace(props as UseMapRecomendPlaceProps<google.maps.Map>)
97
+ : useAmapRecomendPlace(props as UseMapRecomendPlaceProps<AMap.Map>);
98
+ };
@@ -0,0 +1,9 @@
1
+ import { ref } from "vue-demi";
2
+
3
+ export const useUpdate = () => {
4
+ const idx = ref(0);
5
+ const update = () => {
6
+ idx.value += 1;
7
+ };
8
+ return { idx, update };
9
+ };
@@ -0,0 +1,94 @@
1
+ import { computed, reactive } from "vue-demi";
2
+ import { useGeoLocation, UseGeoLocationProps } from "../hooks/useGeoLocation";
3
+ import { useMapDrag, UseMapDragProps } from "../hooks/useMapDrag";
4
+ import type { UseMapPlaceProps } from "../hooks/useMapPlace";
5
+ import { useMapRecomendPlace, UseMapRecomendPlaceProps } from "../hooks/useMapRecomendPlace";
6
+ import type { Place, Point } from "../types/interface";
7
+
8
+ interface CenterPlaceSource {
9
+ source: "geo" | "drag" | "recomend";
10
+ }
11
+ export interface UseBusinessMapRecomendPlaceProps
12
+ extends Pick<
13
+ UseMapRecomendPlaceProps<AMap.Map | google.maps.Map, CenterPlaceSource>,
14
+ "getRecomendPlace" | "mapRef"
15
+ > {
16
+ recomendPlaceGeoLimit: number;
17
+ recomendPlaceDragLimit: number;
18
+ onChangeByDrag?: UseMapDragProps["onChange"];
19
+ onChangeGeoLocation?: UseGeoLocationProps["onChange"];
20
+ onChangePlace?: UseMapPlaceProps["onChange"];
21
+ onChangeRecomandPlace?: UseMapRecomendPlaceProps["onChange"];
22
+ }
23
+ export const useBusinessMapRecomendPlace = (props: UseBusinessMapRecomendPlaceProps) => {
24
+ const centerPlace = reactive<Place>({ lng: 0, lat: 0, name: "" });
25
+ const centerPoint = computed<Point>(() => [centerPlace.lng, centerPlace.lat]);
26
+ const centerSource: CenterPlaceSource = { source: "geo" };
27
+ const {
28
+ mapRef,
29
+ getRecomendPlace,
30
+ recomendPlaceDragLimit,
31
+ recomendPlaceGeoLimit,
32
+ onChangeByDrag,
33
+ onChangeGeoLocation,
34
+ onChangePlace,
35
+ onChangeRecomandPlace,
36
+ } = props;
37
+ const { loading, errorRef } = useGeoLocation({
38
+ mapRef,
39
+ onChange: (value) => {
40
+ centerSource.source = "geo";
41
+ centerPlace.lng = value.position[0];
42
+ centerPlace.lat = value.position[1];
43
+ updatePlace();
44
+ onChangeGeoLocation?.(value);
45
+ },
46
+ });
47
+ const { isDragging } = useMapDrag({
48
+ mapRef,
49
+ onChange: (point) => {
50
+ centerSource.source = "drag";
51
+ centerPlace.lng = point[0];
52
+ centerPlace.lat = point[1];
53
+ updatePlace();
54
+ onChangeByDrag?.(point);
55
+ },
56
+ });
57
+ const { updatePlace, updateRecomandPlace } = useMapRecomendPlace({
58
+ pointRef: centerPoint,
59
+ context: centerSource,
60
+ getRecomendPlace,
61
+ getLimit: (context) => {
62
+ const source = context?.source;
63
+ switch (source) {
64
+ case "drag":
65
+ return recomendPlaceDragLimit;
66
+ case "geo":
67
+ return recomendPlaceGeoLimit;
68
+ default:
69
+ throw new Error(`MyError: should not call getLimit on source: ${source}`);
70
+ }
71
+ },
72
+ mapRef,
73
+ onChangePlace: (place) => {
74
+ Object.assign(centerPlace, { ...place });
75
+ if (centerSource.source !== "recomend") {
76
+ updateRecomandPlace();
77
+ }
78
+ onChangePlace?.(place);
79
+ },
80
+ onChange: (place) => {
81
+ centerSource.source = "recomend";
82
+ Object.assign(centerPlace, { ...place });
83
+ updatePlace();
84
+ onChangeRecomandPlace?.(place);
85
+ },
86
+ });
87
+ return {
88
+ isDragging,
89
+ isGeoLoading: loading,
90
+ geoError: errorRef,
91
+ centerPlace,
92
+ centerPoint,
93
+ };
94
+ };
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import "./style.css";
2
2
  export { AddressBox } from "./business-components/AddressBox";
3
- export { AddressLocator } from "./business-components/AddressLocator";
4
3
  export { DrivingLine } from "./business-components/DrivingLine";
5
4
  export { DrivingRoute } from "./business-components/DrivingRoute";
6
5
  export { PassengerCircle } from "./business-components/PassengerCircle";
@@ -11,8 +10,12 @@ export { TaxiCar } from "./business-components/TaxiCar";
11
10
  export { WalkingLine } from "./business-components/WalkingLine";
12
11
  export { WaveCircle } from "./business-components/WaveCircle";
13
12
  export * from "./components/MapProvider";
13
+ export { useBusinessMapRecomendPlace } from "./hooks-business/useBusinessMapRecomendPlace";
14
14
  export { useDrivingRoute } from "./hooks/useDrivingRoute";
15
+ export { useGeoLocation } from "./hooks/useGeoLocation";
15
16
  export { useHeycarMap } from "./hooks/useHeycarMap";
16
17
  export { useMapAngle } from "./hooks/useMapAngle";
17
18
  export { useMapDrag } from "./hooks/useMapDrag";
19
+ export { useMapPlace } from "./hooks/useMapPlace";
20
+ export { useMapRecomendPlace } from "./hooks/useMapRecomendPlace";
18
21
  export * from "./types/interface";
@@ -2,3 +2,8 @@ import type { ShallowRef } from "vue-demi";
2
2
 
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
+ };
@@ -61,6 +61,18 @@ export function watchPostEffectForDeepOption<T>(
61
61
  });
62
62
  }
63
63
 
64
+ export function watchEffectForDeepOption<T>(
65
+ getOption: () => T,
66
+ callback: WatchCallback<T, T | undefined>,
67
+ watchOptions?: WatchOptions<true>
68
+ ) {
69
+ const memorizedFilter = createDeepCompareMemoize<T>();
70
+ return watch<T, true>(() => memorizedFilter(getOption()), callback, {
71
+ immediate: true,
72
+ ...watchOptions,
73
+ });
74
+ }
75
+
64
76
  function name2setterName<N extends string>(name: N) {
65
77
  return `set${name.charAt(0).toUpperCase()}${name.slice(1)}`;
66
78
  }
@@ -1,3 +1,5 @@
1
+ import type { Place, Point } from "../types/interface";
2
+
1
3
  export const vec2lnglat = ([lng, lat]: [number, number]): google.maps.LatLngLiteral => ({
2
4
  lng,
3
5
  lat,
@@ -35,3 +37,11 @@ export const language2vectorMapForeign = (lang: "en" | "zh"): VectorMapForeign =
35
37
  return "style_zh_cn";
36
38
  }
37
39
  };
40
+
41
+ export const place2point = (place: Place): Point => [place.lng, place.lat];
42
+
43
+ export const pipeAsync =
44
+ <P extends any[]>(fn?: (...args: P) => any) =>
45
+ (...args: P) => {
46
+ setTimeout(() => fn?.(...args));
47
+ };
package/todo.md CHANGED
@@ -1 +1,10 @@
1
1
  https://dawchihliou.github.io/articles/building-custom-google-maps-marker-react-component-like-airbnb-in-nextjs
2
+
3
+ 0. place [0,0] 不应该查询 推荐地址
4
+ 1. map loading place 多次 【0,0】
5
+ 2. Google 地址名称太长
6
+ 3. 中心点 drag 期间位置
7
+ 4. place 需要包含 autocomplete 查询需要的信息
8
+ 5. 高德地图加载期间出现大量的请求
9
+ 6. google/高德 坐标系转化
10
+ 7. 车辆行驶 fitview