@heycar/heycars-map 0.1.2 → 0.1.4
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.
- package/README.md +122 -11
- package/dist/api/geometry.d.ts +1 -2
- package/dist/business-components/DrivingLine/DrivingLine.d.ts +1 -0
- package/dist/business-components/DrivingRoute/DrivingRoute.d.ts +13 -0
- package/dist/business-components/DrivingRoute/index.d.ts +1 -0
- package/dist/business-components/PickupPoints/PickupPoints.d.ts +5 -0
- package/dist/business-components/PickupPoints/index.d.ts +1 -0
- package/dist/business-components/PlaceCircle/PlaceCircle.css.d.ts +28 -3
- package/dist/business-components/PlaceCircle/PlaceCircle.d.ts +2 -2
- package/dist/components/Amap/Amap.d.ts +9 -6
- package/dist/components/Demo/HeycarDemo.d.ts +1 -1
- package/dist/components/Gmap/Gmap.d.ts +7 -5
- package/dist/components/MapProvider/MapProvider.d.ts +6 -2
- package/dist/hooks/useDrivingRoute.d.ts +9 -0
- package/dist/hooks/useHeycarMap.d.ts +1601 -0
- package/dist/hooks/useMapAngle.d.ts +10 -0
- package/dist/hooks/useMapDrag.d.ts +33 -0
- package/dist/index.cjs +56 -56
- package/dist/index.d.ts +6 -2
- package/dist/index.js +1133 -838
- package/dist/style.css +1 -1
- package/dist/types/helper.d.ts +5 -2
- package/dist/types/interface.d.ts +3 -0
- package/dist/types/mapHelper.d.ts +3 -0
- package/dist/utils/transform.d.ts +2 -0
- package/package.json +1 -1
- package/src/api/geometry.ts +2 -1
- package/src/business-components/DrivingLine/DrivingLine.tsx +15 -7
- package/src/business-components/DrivingRoute/DrivingRoute.tsx +48 -0
- package/src/business-components/DrivingRoute/index.ts +1 -0
- package/src/business-components/PickupPoints/PickupPoints.tsx +16 -0
- package/src/business-components/PickupPoints/index.ts +1 -0
- package/src/business-components/PlaceCircle/PlaceCircle.css.ts +39 -8
- package/src/business-components/PlaceCircle/PlaceCircle.tsx +22 -7
- package/src/business-components/TaxiCar/TaxiCar.tsx +3 -2
- package/src/components/Amap/Amap.ts +23 -5
- package/src/components/AmapLoader/AmapLoader.ts +1 -1
- package/src/components/Demo/HeycarDemo.tsx +38 -17
- package/src/components/Gmap/Gmap.ts +14 -7
- package/src/components/MapProvider/MapProvider.tsx +30 -17
- package/src/hooks/useDrivingRoute.ts +73 -0
- package/src/hooks/useHeycarMap.ts +28 -0
- package/src/hooks/useMapAngle.ts +43 -0
- package/src/hooks/useMapDrag.ts +81 -0
- package/src/index.ts +6 -2
- package/src/types/amap/driving.d.ts +2 -0
- package/src/types/helper.ts +38 -8
- package/src/types/interface.ts +3 -0
- package/src/types/mapHelper.ts +1 -0
- package/src/utils/transform.ts +10 -0
- package/dist/hooks/useMapCenter.d.ts +0 -30
- package/src/hooks/useMapCenter.ts +0 -70
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { vec2lnglat } from "../../utils/transform";
|
|
1
|
+
import type { SetMap } from "../../hooks/useHeycarMap";
|
|
2
|
+
import { defineLagecySetup } from "../../types/helper";
|
|
3
|
+
import { language2vectorMapForeign, vec2lnglat } from "../../utils/transform";
|
|
5
4
|
import { Amap, AmapProps } from "../Amap";
|
|
6
5
|
import { AmapLoader } from "../AmapLoader";
|
|
7
|
-
import {
|
|
6
|
+
import { Gmap, GmapProps } from "../Gmap";
|
|
8
7
|
import { GmapLoader, GmapLoaderProps } from "../GmapLoader";
|
|
9
8
|
import { MapSupplierPayolad, provideMapSupplier, useMapSupplier } from "./useMapSupplier";
|
|
10
9
|
|
|
@@ -20,37 +19,45 @@ export const MapProvider = defineLagecySetup(function MapProvider(
|
|
|
20
19
|
export interface HeycarMapProps
|
|
21
20
|
extends Pick<GmapLoaderProps, "fallback" | "loading">,
|
|
22
21
|
Pick<AmapProps, "center" | "zoom"> {
|
|
23
|
-
|
|
22
|
+
language?: "en" | "zh";
|
|
23
|
+
mapRef?: SetMap<AMap.Map> | SetMap<google.maps.Map>;
|
|
24
|
+
onDragEnd?: (value: [number, number]) => any;
|
|
24
25
|
}
|
|
25
|
-
export const HeycarMap =
|
|
26
|
+
export const HeycarMap = defineLagecySetup(function HeycarMap(
|
|
27
|
+
props: HeycarMapProps,
|
|
28
|
+
{ slots, emit }
|
|
29
|
+
) {
|
|
26
30
|
const payload = useMapSupplier();
|
|
27
|
-
const gmapDebouncedEmit
|
|
31
|
+
const gmapDebouncedEmit: GmapProps["onDragEnd"] = ({ target }) => {
|
|
28
32
|
const { lng, lat } = target.getCenter() as google.maps.LatLng;
|
|
29
|
-
emit("
|
|
30
|
-
}
|
|
31
|
-
const amapDebounceEmit
|
|
33
|
+
emit("dragEnd", [lng(), lat()]);
|
|
34
|
+
};
|
|
35
|
+
const amapDebounceEmit: AmapProps["onDragEnd"] = ({ target }) => {
|
|
32
36
|
const { lng, lat } = target.getCenter();
|
|
33
|
-
emit("
|
|
34
|
-
}
|
|
37
|
+
emit("dragEnd", [lng, lat]);
|
|
38
|
+
};
|
|
35
39
|
return () => {
|
|
36
40
|
const { gmapKey, amapKey, amapSecret, amapServiceHost, supplier, gmapId } = payload;
|
|
37
|
-
const {
|
|
41
|
+
const { mapRef: setMap, center, zoom, language = "zh" } = props;
|
|
42
|
+
const { fallback, loading } = slots;
|
|
38
43
|
const children = slots.default?.();
|
|
39
44
|
switch (supplier) {
|
|
40
45
|
case "gmap":
|
|
41
46
|
return (
|
|
42
47
|
<GmapLoader
|
|
43
48
|
apiKey={gmapKey}
|
|
49
|
+
language={language}
|
|
44
50
|
version="beta"
|
|
45
51
|
libraries={["marker", "places", "geometry"]}
|
|
46
52
|
loading={loading}
|
|
47
53
|
fallback={fallback}
|
|
48
54
|
>
|
|
49
55
|
<Gmap
|
|
56
|
+
mapRef={setMap as SetMap<google.maps.Map>}
|
|
50
57
|
mapId={gmapId}
|
|
51
58
|
center={center ? vec2lnglat(center) : undefined}
|
|
52
59
|
zoom={zoom}
|
|
53
|
-
|
|
60
|
+
onDragEnd={gmapDebouncedEmit}
|
|
54
61
|
>
|
|
55
62
|
{children}
|
|
56
63
|
</Gmap>
|
|
@@ -72,11 +79,17 @@ export const HeycarMap = defineSetup(function HeycarMap(props: HeycarMapProps, {
|
|
|
72
79
|
loading={loading}
|
|
73
80
|
fallback={fallback}
|
|
74
81
|
>
|
|
75
|
-
<Amap
|
|
82
|
+
<Amap
|
|
83
|
+
mapRef={setMap as SetMap<AMap.Map>}
|
|
84
|
+
vectorMapForeign={language2vectorMapForeign(language)}
|
|
85
|
+
center={center}
|
|
86
|
+
zoom={zoom}
|
|
87
|
+
onDragEnd={amapDebounceEmit}
|
|
88
|
+
>
|
|
76
89
|
{children}
|
|
77
90
|
</Amap>
|
|
78
91
|
</AmapLoader>
|
|
79
92
|
);
|
|
80
93
|
}
|
|
81
94
|
};
|
|
82
|
-
});
|
|
95
|
+
}).props(["center", "fallback", "loading", "mapRef", "zoom"]);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ShallowRef, shallowRef, watch } from "vue-demi";
|
|
2
|
+
import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
|
|
3
|
+
import type { Point } from "../types/interface";
|
|
4
|
+
|
|
5
|
+
export interface UseDrivingRouteProps {
|
|
6
|
+
from: Point;
|
|
7
|
+
to: Point;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const useADrivingRoute = (props: UseDrivingRouteProps) => {
|
|
11
|
+
const pathRef = shallowRef<Point[]>([]);
|
|
12
|
+
const amapDriving = new AMap.Driving({});
|
|
13
|
+
watch(
|
|
14
|
+
[() => props.from, () => props.to],
|
|
15
|
+
([from, to]) => {
|
|
16
|
+
amapDriving.search(
|
|
17
|
+
AMap.LngLat.from(from),
|
|
18
|
+
AMap.LngLat.from(to),
|
|
19
|
+
{ waypoints: [] },
|
|
20
|
+
(status, result) => {
|
|
21
|
+
switch (status) {
|
|
22
|
+
case "complete": {
|
|
23
|
+
let path: Point[] = [];
|
|
24
|
+
const drivingResult = result as AMap.DrivingResult;
|
|
25
|
+
for (const route of drivingResult.routes) {
|
|
26
|
+
for (const step of route.steps) {
|
|
27
|
+
const basicStep = step as AMap.DriveStepBasic;
|
|
28
|
+
const stepPath = basicStep.path.map<Point>(({ lng, lat }) => [lng, lat]);
|
|
29
|
+
path = path.concat(stepPath);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
pathRef.value = path;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
case "no_data":
|
|
36
|
+
return;
|
|
37
|
+
default:
|
|
38
|
+
throw result;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
{ immediate: true }
|
|
44
|
+
);
|
|
45
|
+
return pathRef;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const useGDrivingRoute = (props: UseDrivingRouteProps) => {
|
|
49
|
+
const pathRef = shallowRef<Point[]>([]);
|
|
50
|
+
const gmapDirectionsService = new google.maps.DirectionsService();
|
|
51
|
+
watch([() => props.from, () => props.to], ([from, to]) => {
|
|
52
|
+
gmapDirectionsService
|
|
53
|
+
.route({
|
|
54
|
+
origin: { lng: from[0], lat: from[1] },
|
|
55
|
+
destination: { lng: to[0], lat: to[1] },
|
|
56
|
+
travelMode: google.maps.TravelMode.WALKING,
|
|
57
|
+
})
|
|
58
|
+
.then((result) => {
|
|
59
|
+
let path: Point[] = [];
|
|
60
|
+
result.routes.map((route) => {
|
|
61
|
+
const stepPath = route.overview_path.map<Point>((item) => [item.lng(), item.lat()]);
|
|
62
|
+
path = path.concat(stepPath);
|
|
63
|
+
});
|
|
64
|
+
pathRef.value = path;
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
return pathRef;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const useDrivingRoute = (props: UseDrivingRouteProps): ShallowRef<Point[]> => {
|
|
71
|
+
const { supplier } = useMapSupplier();
|
|
72
|
+
return supplier === "gmap" ? useGDrivingRoute(props) : useADrivingRoute(props);
|
|
73
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { shallowRef } from "vue-demi";
|
|
2
|
+
import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
|
|
3
|
+
import { vec2lnglat } from "../utils/transform";
|
|
4
|
+
|
|
5
|
+
export type SetMap<M> = (map: M) => void;
|
|
6
|
+
|
|
7
|
+
export const useHeycarAmap = () => {
|
|
8
|
+
const amapRef = shallowRef<AMap.Map>();
|
|
9
|
+
const setMap: SetMap<AMap.Map> = (map) => {
|
|
10
|
+
amapRef.value = map;
|
|
11
|
+
};
|
|
12
|
+
const panTo = (value: [number, number]) => amapRef?.value?.panTo(value);
|
|
13
|
+
return { mapRef: amapRef, panTo, setMap };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const useHeycarGamp = () => {
|
|
17
|
+
const gmapRef = shallowRef<google.maps.Map>();
|
|
18
|
+
const setMap: SetMap<google.maps.Map> = (map) => {
|
|
19
|
+
gmapRef.value = map;
|
|
20
|
+
};
|
|
21
|
+
const panTo = (value: [number, number]) => gmapRef?.value?.panTo(vec2lnglat(value));
|
|
22
|
+
return { mapRef: gmapRef, panTo, setMap };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const useHeycarMap = () => {
|
|
26
|
+
const { supplier } = useMapSupplier();
|
|
27
|
+
return supplier === "gmap" ? useHeycarGamp() : useHeycarAmap();
|
|
28
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { computed, ShallowRef } from "vue";
|
|
2
|
+
import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
|
|
3
|
+
import type { MapShallowRef, Point } from "../types/interface";
|
|
4
|
+
import { vec2lnglat } from "../utils/transform";
|
|
5
|
+
|
|
6
|
+
const amapComputeHeading = (from: Point, to: Point, map?: AMap.Map) => {
|
|
7
|
+
if (!map) return 0;
|
|
8
|
+
const { x: xFrom, y: yFrom } = map.lngLatToContainer(from);
|
|
9
|
+
const { x: xTo, y: yTo } = map.lngLatToContainer(to);
|
|
10
|
+
console.log("yTo - yFrom, xTo - xFrom = ", yTo - yFrom, xTo - xFrom);
|
|
11
|
+
const theta = Math.atan2(yFrom - yTo, xTo - xFrom);
|
|
12
|
+
return ((Math.PI / 2 - theta) / Math.PI) * 180;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export interface UseMapAngleProps<T = AMap.Map | google.maps.Map> {
|
|
16
|
+
pathRef: ShallowRef<Point[]>;
|
|
17
|
+
mapRef?: MapShallowRef<T>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const useAmapAngle = (props: UseMapAngleProps<AMap.Map>) => {
|
|
21
|
+
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);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const useGmapAngle = (props: UseMapAngleProps<google.maps.Map>) => {
|
|
30
|
+
return computed(() => {
|
|
31
|
+
const { pathRef } = props;
|
|
32
|
+
const [from, to] = pathRef.value;
|
|
33
|
+
if (!from || !to) return undefined;
|
|
34
|
+
return google.maps.geometry.spherical.computeHeading(vec2lnglat(from), vec2lnglat(to));
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const useMapAngle = (props: UseMapAngleProps) => {
|
|
39
|
+
const { supplier } = useMapSupplier();
|
|
40
|
+
return supplier === "gmap"
|
|
41
|
+
? useGmapAngle(props as UseMapAngleProps<google.maps.Map>)
|
|
42
|
+
: useAmapAngle(props as UseMapAngleProps<AMap.Map>);
|
|
43
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { reactive, ref, type ShallowRef } from "vue-demi";
|
|
2
|
+
import type { AmapProps } from "../components/Amap";
|
|
3
|
+
import type { GmapProps } from "../components/Gmap";
|
|
4
|
+
import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
|
|
5
|
+
import { LANGUAGE, SetupContextEmitHandler } from "../types/helper";
|
|
6
|
+
import type { MapShallowRef } from "../types/interface";
|
|
7
|
+
import { watchPostEffectForAMapEvent, watchPostEffectForGMapEvent } from "../utils/compare";
|
|
8
|
+
|
|
9
|
+
export const ON_CHANGE_CENTER_INTERVAL = 200;
|
|
10
|
+
export interface UseMapCenterPlace {
|
|
11
|
+
lng: number;
|
|
12
|
+
lat: number;
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
export const useAmapDrag = (amapRef: ShallowRef<AMap.Map | undefined>) => {
|
|
16
|
+
const centerPlace = reactive<UseMapCenterPlace>({ lng: 0, lat: 0, name: "" });
|
|
17
|
+
const isDragging = ref(false);
|
|
18
|
+
const emitDragStart: SetupContextEmitHandler<Pick<AmapProps, "onDragStart">> = () => {
|
|
19
|
+
Promise.resolve().then(() => (isDragging.value = true));
|
|
20
|
+
};
|
|
21
|
+
const emitDragEnd: SetupContextEmitHandler<Pick<AmapProps, "onDragEnd">> = (_, { target }) => {
|
|
22
|
+
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
|
+
});
|
|
38
|
+
};
|
|
39
|
+
watchPostEffectForAMapEvent(amapRef, {} as Pick<AmapProps, "onDragStart">, emitDragStart, [
|
|
40
|
+
"onDragStart",
|
|
41
|
+
]);
|
|
42
|
+
watchPostEffectForAMapEvent(amapRef, {} as Pick<AmapProps, "onDragEnd">, emitDragEnd, [
|
|
43
|
+
"onDragEnd",
|
|
44
|
+
]);
|
|
45
|
+
return { centerPlace, isDragging };
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const useGmapDrag = (gmapRef: ShallowRef<google.maps.Map | undefined>) => {
|
|
49
|
+
const centerPlace = reactive<UseMapCenterPlace>({ lng: 0, lat: 0, name: "" });
|
|
50
|
+
const isDragging = ref(false);
|
|
51
|
+
const emitDragStart: SetupContextEmitHandler<Pick<GmapProps, "onDragStart">> = () => {
|
|
52
|
+
Promise.resolve().then(() => (isDragging.value = true));
|
|
53
|
+
};
|
|
54
|
+
const emitDragEnd: SetupContextEmitHandler<Pick<GmapProps, "onDragEnd">> = async () => {
|
|
55
|
+
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;
|
|
65
|
+
};
|
|
66
|
+
watchPostEffectForGMapEvent(gmapRef!, {} as Pick<GmapProps, "onDragStart">, emitDragStart, [
|
|
67
|
+
"onDragStart",
|
|
68
|
+
]);
|
|
69
|
+
watchPostEffectForGMapEvent(gmapRef!, {} as Pick<GmapProps, "onDragEnd">, emitDragEnd, [
|
|
70
|
+
"onDragEnd",
|
|
71
|
+
]);
|
|
72
|
+
return { centerPlace, isDragging };
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const useMapDrag = (mapRef: MapShallowRef) => {
|
|
76
|
+
const { supplier } = useMapSupplier();
|
|
77
|
+
// todo: 这里违反 react hook 规则,但 react 版本应该可以同时调用 useAmap 和 useGmap
|
|
78
|
+
return supplier === "gmap"
|
|
79
|
+
? useGmapDrag(mapRef as ShallowRef<google.maps.Map | undefined>)
|
|
80
|
+
: useAmapDrag(mapRef as ShallowRef<AMap.Map | undefined>);
|
|
81
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -2,13 +2,17 @@ import "./style.css";
|
|
|
2
2
|
export { AddressBox } from "./business-components/AddressBox";
|
|
3
3
|
export { AddressLocator } from "./business-components/AddressLocator";
|
|
4
4
|
export { DrivingLine } from "./business-components/DrivingLine";
|
|
5
|
+
export { DrivingRoute } from "./business-components/DrivingRoute";
|
|
5
6
|
export { PassengerCircle } from "./business-components/PassengerCircle";
|
|
7
|
+
export { PickupPoints } from "./business-components/PickupPoints";
|
|
6
8
|
export { PlaceCircle } from "./business-components/PlaceCircle";
|
|
7
9
|
export { StartEndPoint } from "./business-components/StartEndPoint";
|
|
8
10
|
export { TaxiCar } from "./business-components/TaxiCar";
|
|
9
11
|
export { WalkingLine } from "./business-components/WalkingLine";
|
|
10
12
|
export { WaveCircle } from "./business-components/WaveCircle";
|
|
11
|
-
export * from "./components/Demo/BusinessDemo";
|
|
12
|
-
export * from "./components/Demo/HeycarDemo";
|
|
13
13
|
export * from "./components/MapProvider";
|
|
14
|
+
export { useDrivingRoute } from "./hooks/useDrivingRoute";
|
|
15
|
+
export { useHeycarMap } from "./hooks/useHeycarMap";
|
|
16
|
+
export { useMapAngle } from "./hooks/useMapAngle";
|
|
17
|
+
export { useMapDrag } from "./hooks/useMapDrag";
|
|
14
18
|
export * from "./types/interface";
|
package/src/types/helper.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "@amap/amap-jsapi-types";
|
|
2
|
+
import { kebabCase } from "lodash-es";
|
|
2
3
|
import { DefineComponent, defineComponent, h, SetupContext, VNode } from "vue-demi";
|
|
3
4
|
|
|
4
5
|
// vue2
|
|
@@ -16,7 +17,13 @@ type LagecyPropNames<N> = N extends `on${string}` ? never : N;
|
|
|
16
17
|
export type EmitByProps<T, R = Required<T>> = {
|
|
17
18
|
[K in keyof R as K extends `on${infer N}` ? Uncapitalize<N> : never]: R[K];
|
|
18
19
|
};
|
|
19
|
-
|
|
20
|
+
export type EmitPayloadByProps<T, R = Required<T>> = {
|
|
21
|
+
[K in keyof R as K extends `on${infer N}` ? Uncapitalize<N> : never]: R[K] extends (
|
|
22
|
+
props: infer P
|
|
23
|
+
) => any
|
|
24
|
+
? P
|
|
25
|
+
: never;
|
|
26
|
+
};
|
|
20
27
|
type RenderFunction = (...args: any[]) => VNodeChild;
|
|
21
28
|
export type SC<P> = Omit<SetupContext<Extract<EmitByProps<P>, ObjectEmitsOptions>>, "slots"> & {
|
|
22
29
|
slots: {
|
|
@@ -27,7 +34,11 @@ export type SC<P> = Omit<SetupContext<Extract<EmitByProps<P>, ObjectEmitsOptions
|
|
|
27
34
|
: never]: P[K];
|
|
28
35
|
} & { default?: Slot };
|
|
29
36
|
};
|
|
30
|
-
|
|
37
|
+
// SetupContextEmitHandler 是通用处理函数的类型,不是严格意义的重载类型
|
|
38
|
+
export type SetupContextEmitHandler<P, E = EmitPayloadByProps<P>> = (
|
|
39
|
+
eventName: keyof E,
|
|
40
|
+
payload: E[keyof E]
|
|
41
|
+
) => any;
|
|
31
42
|
export type SetupOptions<P> = ComponentOptionsBase<
|
|
32
43
|
P,
|
|
33
44
|
Empty,
|
|
@@ -48,7 +59,13 @@ export function defineFc<P = Empty>(render: (props: P, ctx: SC<P>) => VueNode) {
|
|
|
48
59
|
name: render.name,
|
|
49
60
|
inheritAttrs: false,
|
|
50
61
|
setup(_, ctx) {
|
|
51
|
-
const { attrs, slots } = ctx;
|
|
62
|
+
const { attrs, slots, emit } = ctx;
|
|
63
|
+
const originEmit = emit as EmitFn;
|
|
64
|
+
const emitKebab = (eventName: string, data: any) => {
|
|
65
|
+
const kebabName = kebabCase(eventName);
|
|
66
|
+
originEmit(eventName, data);
|
|
67
|
+
if (eventName !== kebabName) originEmit(kebabName, data);
|
|
68
|
+
};
|
|
52
69
|
const props = attrs as unknown as P;
|
|
53
70
|
// todo: 下面是实时订阅的实现,是否不需要。
|
|
54
71
|
const proxiedSlots = new Proxy(slots, {
|
|
@@ -56,7 +73,8 @@ export function defineFc<P = Empty>(render: (props: P, ctx: SC<P>) => VueNode) {
|
|
|
56
73
|
return Reflect.get(target, name, receiver) ?? Reflect.get(props as any, name);
|
|
57
74
|
},
|
|
58
75
|
});
|
|
59
|
-
return () =>
|
|
76
|
+
return () =>
|
|
77
|
+
render(props, { ...ctx, slots: proxiedSlots, emit: emitKebab } as unknown as SC<P>);
|
|
60
78
|
},
|
|
61
79
|
}) as DefineComponent<
|
|
62
80
|
ComponentObjectPropsOptions<P>,
|
|
@@ -77,14 +95,20 @@ export function defineSetup<P>(setup: (props: P, ctx: SC<P>) => () => VueNode) {
|
|
|
77
95
|
name: setup.name,
|
|
78
96
|
inheritAttrs: false,
|
|
79
97
|
setup(_, ctx) {
|
|
80
|
-
const { attrs, slots } = ctx;
|
|
98
|
+
const { attrs, slots, emit } = ctx;
|
|
81
99
|
const props = attrs as unknown as P;
|
|
100
|
+
const originEmit = emit as EmitFn;
|
|
101
|
+
const emitKebab = (eventName: string, data: any) => {
|
|
102
|
+
const kebabName = kebabCase(eventName);
|
|
103
|
+
originEmit(eventName, data);
|
|
104
|
+
if (eventName !== kebabName) originEmit(kebabName, data);
|
|
105
|
+
};
|
|
82
106
|
const proxiedSlots = new Proxy(slots, {
|
|
83
107
|
get(target, name, receiver) {
|
|
84
108
|
return Reflect.get(target, name, receiver) ?? Reflect.get(props as any, name);
|
|
85
109
|
},
|
|
86
110
|
});
|
|
87
|
-
return setup(props, { ...ctx, slots: proxiedSlots } as unknown as SC<P>);
|
|
111
|
+
return setup(props, { ...ctx, slots: proxiedSlots, emit: emitKebab } as unknown as SC<P>);
|
|
88
112
|
},
|
|
89
113
|
}) as DefineComponent<
|
|
90
114
|
ComponentObjectPropsOptions<P>,
|
|
@@ -109,13 +133,19 @@ export function defineLagecySetup<P>(setup: (props: P, ctx: SC<P>) => () => VueN
|
|
|
109
133
|
props: propNames as string[],
|
|
110
134
|
setup(setupProps, ctx) {
|
|
111
135
|
const props = setupProps as P;
|
|
112
|
-
const { slots } = ctx;
|
|
136
|
+
const { slots, emit } = ctx;
|
|
137
|
+
const originEmit = emit as EmitFn;
|
|
138
|
+
const emitKebab = (eventName: string, data: any) => {
|
|
139
|
+
const kebabName = kebabCase(eventName);
|
|
140
|
+
originEmit(eventName, data);
|
|
141
|
+
if (eventName !== kebabName) originEmit(kebabName, data);
|
|
142
|
+
};
|
|
113
143
|
const proxiedSlots = new Proxy(slots, {
|
|
114
144
|
get(target, name, receiver) {
|
|
115
145
|
return Reflect.get(target, name, receiver) ?? Reflect.get(props as any, name);
|
|
116
146
|
},
|
|
117
147
|
});
|
|
118
|
-
return setup(props, { ...ctx, slots: proxiedSlots } as unknown as SC<P>);
|
|
148
|
+
return setup(props, { ...ctx, slots: proxiedSlots, emit: emitKebab } as unknown as SC<P>);
|
|
119
149
|
},
|
|
120
150
|
}) as DefineComponent<
|
|
121
151
|
ComponentObjectPropsOptions<P>,
|
package/src/types/interface.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type MapEventHandler<T> = (e: { target: T }) => any;
|
package/src/utils/transform.ts
CHANGED
|
@@ -25,3 +25,13 @@ export const property2emitEventName = (propertyName: string) => {
|
|
|
25
25
|
export const property2mapEventName = (propertyName: string) => {
|
|
26
26
|
return propertyName.slice(2).toLowerCase();
|
|
27
27
|
};
|
|
28
|
+
|
|
29
|
+
export type VectorMapForeign = "style_en" | "style_local" | "style_zh_cn";
|
|
30
|
+
export const language2vectorMapForeign = (lang: "en" | "zh"): VectorMapForeign => {
|
|
31
|
+
switch (lang) {
|
|
32
|
+
case "en":
|
|
33
|
+
return "style_en";
|
|
34
|
+
case "zh":
|
|
35
|
+
return "style_zh_cn";
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export declare const ON_CHANGE_CENTER_INTERVAL = 200;
|
|
2
|
-
export interface UseMapCenterData {
|
|
3
|
-
lng: number;
|
|
4
|
-
lat: number;
|
|
5
|
-
name: string;
|
|
6
|
-
}
|
|
7
|
-
export declare const useAmapCenter: () => {
|
|
8
|
-
center: {
|
|
9
|
-
lng: number;
|
|
10
|
-
lat: number;
|
|
11
|
-
name: string;
|
|
12
|
-
};
|
|
13
|
-
setCenter: (value: [number, number]) => void | undefined;
|
|
14
|
-
};
|
|
15
|
-
export declare const useGmapCenter: () => {
|
|
16
|
-
center: {
|
|
17
|
-
lng: number;
|
|
18
|
-
lat: number;
|
|
19
|
-
name: string;
|
|
20
|
-
};
|
|
21
|
-
setCenter: (value: [number, number]) => void | undefined;
|
|
22
|
-
};
|
|
23
|
-
export declare const useMapCenter: () => {
|
|
24
|
-
center: {
|
|
25
|
-
lng: number;
|
|
26
|
-
lat: number;
|
|
27
|
-
name: string;
|
|
28
|
-
};
|
|
29
|
-
setCenter: (value: [number, number]) => void | undefined;
|
|
30
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { debounce } from "lodash-es";
|
|
2
|
-
import { reactive } from "vue-demi";
|
|
3
|
-
import type { AmapProps } from "../components/Amap";
|
|
4
|
-
import { useAmap } from "../components/Amap/useAmap";
|
|
5
|
-
import type { GampProps } from "../components/Gmap";
|
|
6
|
-
import { useGmap } from "../components/Gmap/useGmap";
|
|
7
|
-
import { useMapSupplier } from "../components/MapProvider/useMapSupplier";
|
|
8
|
-
import { LANGUAGE, SetupContextEmit } from "../types/helper";
|
|
9
|
-
import { watchPostEffectForAMapEvent, watchPostEffectForGMapEvent } from "../utils/compare";
|
|
10
|
-
import { vec2lnglat } from "../utils/transform";
|
|
11
|
-
|
|
12
|
-
export const ON_CHANGE_CENTER_INTERVAL = 200;
|
|
13
|
-
export interface UseMapCenterData {
|
|
14
|
-
lng: number;
|
|
15
|
-
lat: number;
|
|
16
|
-
name: string;
|
|
17
|
-
}
|
|
18
|
-
export const useAmapCenter = () => {
|
|
19
|
-
const amapRef = useAmap();
|
|
20
|
-
const centerData = reactive<UseMapCenterData>({ lng: 0, lat: 0, name: "" });
|
|
21
|
-
const setCenter = (value: [number, number]) => amapRef?.value?.setCenter(value);
|
|
22
|
-
const debouncedEmit = debounce<SetupContextEmit<AmapProps>>((_, { target }) => {
|
|
23
|
-
const center = target.getCenter();
|
|
24
|
-
centerData.lng = center.lng;
|
|
25
|
-
centerData.lat = center.lat;
|
|
26
|
-
const geocoder = new AMap.Geocoder({ lang: LANGUAGE });
|
|
27
|
-
geocoder.getAddress(center, (status, result) => {
|
|
28
|
-
switch (status) {
|
|
29
|
-
case "complete":
|
|
30
|
-
centerData.name = (result as AMap.ReGeocoderResult).regeocode.formattedAddress;
|
|
31
|
-
return;
|
|
32
|
-
case "no_data":
|
|
33
|
-
return;
|
|
34
|
-
case "error":
|
|
35
|
-
throw result;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}, ON_CHANGE_CENTER_INTERVAL);
|
|
39
|
-
watchPostEffectForAMapEvent(amapRef!, {} as AmapProps, debouncedEmit, ["onMapMove"]);
|
|
40
|
-
return { center: centerData, setCenter };
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const useGmapCenter = () => {
|
|
44
|
-
const gmapRef = useGmap();
|
|
45
|
-
const centerData = reactive<UseMapCenterData>({ lng: 0, lat: 0, name: "" });
|
|
46
|
-
const setCenter = (value: [number, number]) => gmapRef?.value?.setCenter(vec2lnglat(value));
|
|
47
|
-
const debouncedEmit = debounce<SetupContextEmit<GampProps>>(async (_, { target }) => {
|
|
48
|
-
const center = target.getCenter();
|
|
49
|
-
const lng = center?.lng();
|
|
50
|
-
const lat = center?.lat();
|
|
51
|
-
if (lng) centerData.lng = lng;
|
|
52
|
-
if (lat) centerData.lat = lat;
|
|
53
|
-
const geocoder = new google.maps.Geocoder();
|
|
54
|
-
const { results } = await geocoder.geocode({ language: LANGUAGE, location: center });
|
|
55
|
-
centerData.name = results[0].formatted_address;
|
|
56
|
-
}, ON_CHANGE_CENTER_INTERVAL);
|
|
57
|
-
watchPostEffectForGMapEvent(gmapRef!, {} as GampProps, debouncedEmit, ["onCenter_changed"]);
|
|
58
|
-
return { center: centerData, setCenter };
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const useMapCenter = () => {
|
|
62
|
-
const payload = useMapSupplier();
|
|
63
|
-
// todo: 这里违反 react hook 规则,但 react 版本应该可以同时调用 useAmap 和 useGmap
|
|
64
|
-
switch (payload.supplier) {
|
|
65
|
-
case "gmap":
|
|
66
|
-
return useGmapCenter();
|
|
67
|
-
default:
|
|
68
|
-
return useAmapCenter();
|
|
69
|
-
}
|
|
70
|
-
};
|