@heycar/heycars-map 0.2.2 → 0.2.3

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 (32) hide show
  1. package/dist/api/geometry.d.ts +3 -3
  2. package/dist/business-components/PassengerCircle/PassengerCircle.css.d.ts +14 -1
  3. package/dist/business-components/PassengerCircle/PassengerCircle.d.ts +1 -0
  4. package/dist/business-components/PlaceCircle/PlaceCircle.css.d.ts +8 -1
  5. package/dist/business-components/PlaceCircle/PlaceCircle.d.ts +1 -0
  6. package/dist/hooks/useDrivingRoute.d.ts +12 -5
  7. package/dist/hooks/useGeoLocation.d.ts +1 -1
  8. package/dist/hooks/useMapGeometry.d.ts +10 -0
  9. package/dist/index.cjs +45 -45
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +929 -825
  12. package/dist/style.css +1 -1
  13. package/dist/types/interface.d.ts +5 -0
  14. package/package.json +1 -1
  15. package/src/api/geometry.ts +3 -4
  16. package/src/business-components/DrivingRoute/DrivingRoute.tsx +5 -5
  17. package/src/business-components/PassengerCircle/PassengerCircle.css.ts +19 -6
  18. package/src/business-components/PassengerCircle/PassengerCircle.tsx +14 -8
  19. package/src/business-components/PlaceCircle/PlaceCircle.css.ts +14 -4
  20. package/src/business-components/PlaceCircle/PlaceCircle.tsx +30 -24
  21. package/src/business-components/WalkingLine/WalkingLine.tsx +6 -2
  22. package/src/business-components/WalkingRoute/WalkingRoute.tsx +2 -8
  23. package/src/components/Demo/HeycarDemo.tsx +20 -8
  24. package/src/hooks/useDrivingRoute.ts +57 -25
  25. package/src/hooks/useGeoLocation.ts +2 -2
  26. package/src/hooks/useMapGeometry.ts +27 -0
  27. package/src/hooks/useMapLoader.ts +1 -1
  28. package/src/hooks/useWalkingRoute.ts +24 -11
  29. package/src/index.ts +1 -0
  30. package/src/types/amap/plugin.d.ts +1 -1
  31. package/src/types/interface.ts +6 -0
  32. package/todo.md +10 -5
package/dist/style.css CHANGED
@@ -1 +1 @@
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}
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}._1l6offo1{width:4.53vw;height:4.53vw;margin-bottom:-2.265vw}._1l6offo2{width:16.27vw;height:16.27vw;margin-bottom:-8.135vw}.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{opacity:0}.fhyw8b{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}
@@ -25,3 +25,8 @@ export interface RegisterOverlay<T> {
25
25
  add: (overlay: T) => void;
26
26
  remove: (overlay: T) => void;
27
27
  }
28
+ export interface Route {
29
+ path: Point[];
30
+ distance: number;
31
+ duration: number;
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heycar/heycars-map",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite -c vite.config.dev.ts",
@@ -5,11 +5,10 @@ export interface ApiMapMeta {
5
5
  }
6
6
 
7
7
  const point2latlng = ([lng, lat]: Point): google.maps.LatLngLiteral => ({ lng, lat });
8
-
9
8
  export interface DistanceOfLineProps extends ApiMapMeta {
10
9
  path: Point[];
11
10
  }
12
- export function apiDistanceOfLine(props: DistanceOfLineProps): number {
11
+ export function apiMapDistanceOfLine(props: DistanceOfLineProps): number {
13
12
  const { path, isGoogle } = props;
14
13
  if (!isGoogle) {
15
14
  return AMap.GeometryUtil.distanceOfLine(path);
@@ -21,7 +20,7 @@ export interface IsPointInRingProps extends ApiMapMeta {
21
20
  point: Point;
22
21
  path: Point[];
23
22
  }
24
- export function apiIsPointInRing(props: IsPointInRingProps): boolean {
23
+ export function apiMapIsPointInRing(props: IsPointInRingProps): boolean {
25
24
  const { point, path, isGoogle } = props;
26
25
  if (!isGoogle) {
27
26
  return AMap.GeometryUtil.isPointInRing(point, path);
@@ -35,7 +34,7 @@ export interface IsPointInLineProps extends ApiMapMeta {
35
34
  path: Point[];
36
35
  tolerance: number;
37
36
  }
38
- export function apiIsPointInLine(props: IsPointInLineProps): boolean {
37
+ export function apiMapIsPointInLine(props: IsPointInLineProps): boolean {
39
38
  const { point, path, tolerance, isGoogle } = props;
40
39
  if (!isGoogle) {
41
40
  return AMap.GeometryUtil.isPointOnLine(point, path, tolerance);
@@ -1,4 +1,4 @@
1
- import { reactive, VNodeData } from "vue-demi";
1
+ import { reactive, toRefs, VNodeData } from "vue-demi";
2
2
  import {
3
3
  useADrivingRoute,
4
4
  UseDrivingRouteProps,
@@ -22,9 +22,9 @@ export const ADrivingRoute = defineSetup(function DrivingRoute(
22
22
  { slots }
23
23
  ) {
24
24
  const map = useAmap();
25
- const path = useADrivingRoute(props);
25
+ const { path, distance, duration } = toRefs(useADrivingRoute(props));
26
26
  const angle = useAmapAngle(reactive({ path, map }));
27
- return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
27
+ return () => <div>{slots.render?.(reactive({ path, angle, distance, duration }))}</div>;
28
28
  });
29
29
 
30
30
  export const GDrivingRoute = defineSetup(function DrivingRoute(
@@ -32,9 +32,9 @@ export const GDrivingRoute = defineSetup(function DrivingRoute(
32
32
  { slots }
33
33
  ) {
34
34
  const map = useGmap();
35
- const path = useGDrivingRoute(props);
35
+ const { path, distance, duration } = toRefs(useGDrivingRoute(props));
36
36
  const angle = useGmapAngle(reactive({ path, map }));
37
- return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
37
+ return () => <div>{slots.render?.(reactive({ path, angle, distance, duration }))}</div>;
38
38
  });
39
39
 
40
40
  export const DrivingRoute = defineSetup(function DrivingRoute(props: DrivingRouteProps, { slots }) {
@@ -1,8 +1,21 @@
1
- import { style } from "@vanilla-extract/css";
1
+ import { recipe } from "@vanilla-extract/recipes";
2
2
 
3
- export const passengerCircle = style({
4
- display: "flex",
5
- marginBottom: "-8.135vw",
6
- width: "16.27vw",
7
- height: "16.27vw",
3
+ export const passengerCircle = recipe({
4
+ base: {
5
+ display: "flex",
6
+ },
7
+ variants: {
8
+ size: {
9
+ small: {
10
+ width: "4.53vw",
11
+ height: "4.53vw",
12
+ marginBottom: "-2.265vw",
13
+ },
14
+ large: {
15
+ width: "16.27vw",
16
+ height: "16.27vw",
17
+ marginBottom: "-8.135vw",
18
+ },
19
+ },
20
+ },
8
21
  });
@@ -1,5 +1,6 @@
1
1
  import { computed } from "vue";
2
2
  import imgPassengerCircle from "../../assets/icons/svg/passenger-circle.svg";
3
+ import imgPlaceCircle from "../../assets/icons/svg/place-circle.svg";
3
4
  import { AmapMarker } from "../../components/AmapMarker";
4
5
  import { GmapAdvancedMarkerView } from "../../components/GmapAdvancedMarkerView";
5
6
  import { useMapSupplier } from "../../hooks/useMapSupplier";
@@ -11,22 +12,27 @@ import * as css from "./PassengerCircle.css";
11
12
 
12
13
  interface PassengerCircleProps {
13
14
  position: [number, number];
15
+ size?: "small" | "large";
14
16
  }
15
17
  export const APassengerCircle = defineSetup(function APassengerCircle(props: PassengerCircleProps) {
16
- const contentRef = computed(
17
- () => `
18
- <img src="${imgPassengerCircle}" class="${css.passengerCircle}">
19
- `
20
- );
18
+ const contentRef = computed(() => {
19
+ const { size = "large" } = props;
20
+ const src = size === "large" ? imgPassengerCircle : imgPlaceCircle;
21
+ return `
22
+ <img src="${src}" class="${css.passengerCircle({ size })}">
23
+ `;
24
+ });
21
25
  return () => (
22
26
  <AmapMarker position={props.position} content={contentRef.value} anchor={"bottom-center"} />
23
27
  );
24
28
  });
25
29
 
26
30
  export const GPassengerCircle = defineSetup(function GPassengerCircle(props: PassengerCircleProps) {
27
- const contentRef = computed(() =>
28
- createDom("img", { class: css.passengerCircle, src: imgPassengerCircle })
29
- );
31
+ const contentRef = computed(() => {
32
+ const { size = "large" } = props;
33
+ const src = size === "large" ? imgPassengerCircle : imgPlaceCircle;
34
+ return createDom("img", { class: css.passengerCircle({ size }), src });
35
+ });
30
36
  return () => (
31
37
  <GmapAdvancedMarkerView position={vec2lnglat(props.position)} content={contentRef.value} />
32
38
  );
@@ -45,10 +45,20 @@ export const gmapPlaceIconLayout = recipe({
45
45
  },
46
46
  });
47
47
 
48
- export const placeIcon = style({
49
- display: "flex",
50
- width: "4.53vw",
51
- height: "4.53vw",
48
+ export const placeIcon = recipe({
49
+ base: {
50
+ display: "flex",
51
+ width: "4.53vw",
52
+ height: "4.53vw",
53
+ },
54
+ variants: {
55
+ hideIcon: {
56
+ true: {
57
+ opacity: 0,
58
+ },
59
+ false: {},
60
+ },
61
+ },
52
62
  });
53
63
 
54
64
  export const label = style({
@@ -13,25 +13,27 @@ export interface PlaceCircleProps {
13
13
  position: [number, number];
14
14
  label?: string;
15
15
  textAlign?: "left" | "right";
16
+ hideIcon?: boolean;
16
17
  }
17
18
  export const APlaceCircle = defineSetup(function APlaceCircle(props: PlaceCircleProps) {
18
19
  const textAlignRef = computed(() => props.textAlign ?? "right");
19
- const contentRef = computed(
20
- () => `
21
- <div class="${css.placeCircleLayout({ textAlign: textAlignRef.value })}" >
22
- <img class="${css.placeIcon} ${css.amapPlaceIconLayout({
20
+ const contentRef = computed(() => {
21
+ const { hideIcon = false } = props;
22
+ return `
23
+ <div class="${css.placeCircleLayout({ textAlign: textAlignRef.value })}">
24
+ <img class="${css.placeIcon({ hideIcon })} ${css.amapPlaceIconLayout({
23
25
  textAlign: textAlignRef.value,
24
26
  })}" src="${imgPlaceCircle}">
25
- <div class="${css.label}">${props.label}</div>
26
- </div>
27
- `
28
- );
29
- const contentWithoutLabelRef = computed(
30
- () =>
31
- `<img class="${css.placeIcon} ${css.amapPlaceIconLayout({
32
- textAlign: textAlignRef.value,
33
- })}" src="${imgPlaceCircle}">`
34
- );
27
+ <div class="${css.label}">${props.label}</div>
28
+ </div>
29
+ `;
30
+ });
31
+ const contentWithoutLabelRef = computed(() => {
32
+ const { hideIcon = false } = props;
33
+ return `<img class="${css.placeIcon({ hideIcon })} ${css.amapPlaceIconLayout({
34
+ textAlign: textAlignRef.value,
35
+ })}" src="${imgPlaceCircle}">`;
36
+ });
35
37
  return () => (
36
38
  <AmapMarker
37
39
  position={props.position}
@@ -43,8 +45,9 @@ export const APlaceCircle = defineSetup(function APlaceCircle(props: PlaceCircle
43
45
 
44
46
  export const GPlaceCircle = defineSetup(function GPlaceCircle(props: PlaceCircleProps) {
45
47
  const textAlignRef = computed(() => props.textAlign ?? "right");
46
- const contentRef = computed(() =>
47
- createDom(
48
+ const contentRef = computed(() => {
49
+ const { hideIcon = false } = props;
50
+ return createDom(
48
51
  "div",
49
52
  {
50
53
  class: `${css.placeCircleLayout({
@@ -52,17 +55,20 @@ export const GPlaceCircle = defineSetup(function GPlaceCircle(props: PlaceCircle
52
55
  })} ${css.gmapPlaceIconLayout({ textAlign: textAlignRef.value })}`,
53
56
  },
54
57
  `
55
- <img class="${css.placeIcon}" src="${imgPlaceCircle}">
58
+ <img class="${css.placeIcon({ hideIcon })}" src="${imgPlaceCircle}">
56
59
  <div class="${css.label}">${props.label}</div>
57
60
  `
58
- )
59
- );
60
- const contentWithoutLabelRef = computed(() =>
61
- createDom("img", {
62
- class: `${css.placeIcon} ${css.gmapPlaceIconLayout({ textAlign: textAlignRef.value })}`,
61
+ );
62
+ });
63
+ const contentWithoutLabelRef = computed(() => {
64
+ const { hideIcon = false } = props;
65
+ return createDom("img", {
66
+ class: `${css.placeIcon({ hideIcon })} ${css.gmapPlaceIconLayout({
67
+ textAlign: textAlignRef.value,
68
+ })}`,
63
69
  src: imgPlaceCircle,
64
- })
65
- );
70
+ });
71
+ });
66
72
  return () => (
67
73
  <GmapAdvancedMarkerView
68
74
  position={vec2lnglat(props.position)}
@@ -10,11 +10,13 @@ export interface WalkingLineProps {
10
10
  }
11
11
  export const AWalkingLine = defineSetup(function AWalkingLine(props: WalkingLineProps) {
12
12
  return () => {
13
+ const { path } = props;
14
+ if (path.length === 0) return null;
13
15
  const vw = window.innerWidth * 0.01;
14
16
  const strokeWidth = 2 * vw;
15
17
  return (
16
18
  <AmapPolyline
17
- path={props.path}
19
+ path={path}
18
20
  strokeWeight={strokeWidth}
19
21
  strokeOpacity={1}
20
22
  strokeColor={"#38A3FE"}
@@ -30,12 +32,14 @@ export const AWalkingLine = defineSetup(function AWalkingLine(props: WalkingLine
30
32
  export const GWalkingLine = defineSetup(function GWalkingLine(props: WalkingLineProps) {
31
33
  const pathRef = computed(() => props.path.map(vec2lnglat));
32
34
  return () => {
35
+ const path = pathRef.value;
36
+ if (path.length === 0) return null;
33
37
  const vw = window.innerWidth * 0.01;
34
38
  const strokeWidth = 2 * vw;
35
39
  const r = strokeWidth / 4;
36
40
  return (
37
41
  <GmapPolyline
38
- path={pathRef.value}
42
+ path={path}
39
43
  strokeWeight={strokeWidth}
40
44
  strokeOpacity={1}
41
45
  strokeColor={"transparent"}
@@ -1,6 +1,4 @@
1
1
  import { reactive, VNodeData } from "vue-demi";
2
- import { useAmap, useGmap } from "../../hooks/useMap";
3
- import { useAmapAngle, useGmapAngle } from "../../hooks/useMapAngle";
4
2
  import { useMapSupplier } from "../../hooks/useMapSupplier";
5
3
  import {
6
4
  useAWalkingRoute,
@@ -21,20 +19,16 @@ export const AWalkingRoute = defineSetup(function WalkingRoute(
21
19
  props: WalkingRouteProps,
22
20
  { slots }
23
21
  ) {
24
- const map = useAmap();
25
22
  const path = useAWalkingRoute(props);
26
- const angle = useAmapAngle(reactive({ path, map }));
27
- return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
23
+ return () => <div>{slots.render?.(reactive({ path }))}</div>;
28
24
  });
29
25
 
30
26
  export const GWalkingRoute = defineSetup(function WalkingRoute(
31
27
  props: WalkingRouteProps,
32
28
  { slots }
33
29
  ) {
34
- const map = useGmap();
35
30
  const path = useGWalkingRoute(props);
36
- const angle = useGmapAngle(reactive({ path, map }));
37
- return () => <div>{slots.render?.(reactive({ path, angle }))}</div>;
31
+ return () => <div>{slots.render?.(reactive({ path }))}</div>;
38
32
  });
39
33
 
40
34
  export const WalkingRoute = defineSetup(function WalkingRoute(props: WalkingRouteProps, { slots }) {
@@ -1,5 +1,7 @@
1
1
  import { computed } from "vue-demi";
2
- import { StartEndPoint } from "../../business-components/StartEndPoint";
2
+ import { PlaceCircle } from "../../business-components/PlaceCircle";
3
+ import { WalkingLine } from "../../business-components/WalkingLine";
4
+ import { WalkingRoute } from "../../business-components/WalkingRoute";
3
5
  import { useBusinessMapAutoComplete } from "../../hooks-business/useBusinessMapAutoComplete";
4
6
  import {
5
7
  useBusinessMapRecomendPlace,
@@ -7,6 +9,7 @@ import {
7
9
  } from "../../hooks-business/useBusinessMapRecomendPlace";
8
10
  import { useHeycarMap } from "../../hooks/useHeycarMap";
9
11
  import { useMapFitView } from "../../hooks/useMapFitView";
12
+ import { useMapGeometry } from "../../hooks/useMapGeometry";
10
13
  import { defineSetup } from "../../types/helper";
11
14
  import { HeycarMap, MapProvider } from "../MapProvider/MapProvider";
12
15
  import * as css from "./Demo.css";
@@ -94,11 +97,18 @@ export const SomeHomePage = defineSetup(function SomeHomePage() {
94
97
  padding: [15, 15, 5, 15],
95
98
  autoFitTimeout: 5000,
96
99
  });
100
+ const { apiMapDistance } = useMapGeometry();
97
101
  (window as any).setCenterPlaceByRecomand = setCenterPlaceByRecomand;
98
102
  (window as any).setFitView = setFitView;
99
103
  return () => {
100
104
  return (
101
105
  <div>
106
+ distance:{" "}
107
+ {apiMapDistance(centerPoint.value, [
108
+ centerPoint.value[0] + 0.01,
109
+ centerPoint.value[1] + 0.01,
110
+ ])}{" "}
111
+ <br />
102
112
  geoLoading: {`${geoLoading.value}`} <br />
103
113
  isDragging: {`${isDragging.value}`} <br />
104
114
  geoPosition: {geoPosition.value[0]} | {geoPosition.value[1]} <br />
@@ -112,18 +122,18 @@ export const SomeHomePage = defineSetup(function SomeHomePage() {
112
122
  zoom={centerPoint.value[0] === 0 ? 3 : 13}
113
123
  mapRef={setMap}
114
124
  >
115
- <StartEndPoint
125
+ {/* <StartEndPoint
116
126
  registerOverlay={registerFitVeiw}
117
127
  position={[121.4897065, 31.0842552]}
118
128
  title={"start point"}
119
129
  type="start"
120
- />
121
- <StartEndPoint
130
+ /> */}
131
+ {/* <StartEndPoint
122
132
  registerOverlay={registerFitVeiw}
123
133
  position={[centerPoint.value[0] + 0.01, centerPoint.value[1] + 0.01]}
124
134
  title={"end point"}
125
135
  type="end"
126
- />
136
+ /> */}
127
137
  {/* <PickupPoints places={placeCandidates.value} /> */}
128
138
  {/* <AddressBox
129
139
  type="box"
@@ -147,11 +157,13 @@ export const SomeHomePage = defineSetup(function SomeHomePage() {
147
157
  <TaxiCar position={[121, 31]} angle={angle} />,
148
158
  ]}
149
159
  /> */}
150
- {/* <WalkingRoute
160
+ {/* <PassengerCircle position={centerPoint.value} size="small" /> */}
161
+ <PlaceCircle position={centerPoint.value} label={"some place"} hideIcon />
162
+ <WalkingRoute
151
163
  from={centerPoint.value}
152
- to={[centerPoint.value[0] + 0.1, centerPoint.value[1] + 0.1]}
164
+ to={[centerPoint.value[0] + 0.01, centerPoint.value[1] + 0.01]}
153
165
  render={({ path }) => <WalkingLine path={path} />}
154
- /> */}
166
+ />
155
167
  </HeycarMap>
156
168
  </div>
157
169
  );
@@ -1,5 +1,5 @@
1
- import { ShallowRef, shallowRef } from "vue-demi";
2
- import type { Point } from "../types/interface";
1
+ import { reactive } from "vue-demi";
2
+ import type { Point, Route } from "../types/interface";
3
3
  import { watchPostEffectForDeepOption } from "../utils/compare";
4
4
  import { useMapSupplier } from "./useMapSupplier";
5
5
 
@@ -9,7 +9,7 @@ export interface UseDrivingRouteProps {
9
9
  }
10
10
 
11
11
  export const useADrivingRoute = (props: UseDrivingRouteProps) => {
12
- const pathRef = shallowRef<Point[]>([]);
12
+ const outputRoute = reactive<Route>({ path: [], distance: 0, duration: 0 });
13
13
  const amapDriving = new AMap.Driving({});
14
14
  watchPostEffectForDeepOption(
15
15
  () => ({ ...props }),
@@ -23,17 +23,22 @@ export const useADrivingRoute = (props: UseDrivingRouteProps) => {
23
23
  case "complete": {
24
24
  let path: Point[] = [];
25
25
  const drivingResult = result as AMap.DrivingResult;
26
- for (const route of drivingResult.routes) {
27
- for (const step of route.steps) {
28
- const basicStep = step as AMap.DriveStepBasic;
29
- const stepPath = basicStep.path.map<Point>(({ lng, lat }) => [lng, lat]);
30
- path = path.concat(stepPath);
31
- }
26
+ // todo 多条导航路线的情况
27
+ const firstRoute = drivingResult.routes[0];
28
+ for (const step of firstRoute.steps) {
29
+ const basicStep = step as AMap.DriveStepBasic;
30
+ const stepPath = basicStep.path.map<Point>(({ lng, lat }) => [lng, lat]);
31
+ path = path.concat(stepPath);
32
32
  }
33
- pathRef.value = path;
33
+ outputRoute.path = path;
34
+ outputRoute.distance = firstRoute.distance;
35
+ outputRoute.duration = firstRoute.time;
34
36
  return;
35
37
  }
36
38
  case "no_data":
39
+ outputRoute.path = [];
40
+ outputRoute.distance = 0;
41
+ outputRoute.duration = 0;
37
42
  return;
38
43
  default:
39
44
  throw result;
@@ -42,35 +47,62 @@ export const useADrivingRoute = (props: UseDrivingRouteProps) => {
42
47
  );
43
48
  }
44
49
  );
45
- return pathRef;
50
+ return outputRoute;
46
51
  };
47
52
 
48
53
  export const useGDrivingRoute = (props: UseDrivingRouteProps) => {
49
- const pathRef = shallowRef<Point[]>([]);
54
+ const outputRoute = reactive<Route>({ path: [], distance: 0, duration: 0 });
50
55
  const gmapDirectionsService = new google.maps.DirectionsService();
51
56
  watchPostEffectForDeepOption(
52
57
  () => ({ ...props }),
53
58
  ({ from, to }) => {
54
- gmapDirectionsService
55
- .route({
59
+ gmapDirectionsService.route(
60
+ {
56
61
  origin: { lng: from[0], lat: from[1] },
57
62
  destination: { lng: to[0], lat: to[1] },
58
63
  travelMode: google.maps.TravelMode.DRIVING,
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;
67
- });
64
+ },
65
+ (result, status) => {
66
+ switch (status) {
67
+ case google.maps.DirectionsStatus.OK: {
68
+ let path: Point[] = [];
69
+ let distance = 0;
70
+ let duration = 0;
71
+ const firstRoute = result!.routes[0];
72
+
73
+ const stepPath = firstRoute.overview_path.map<Point>((item) => [
74
+ item.lng(),
75
+ item.lat(),
76
+ ]);
77
+ path = path.concat(stepPath);
78
+
79
+ for (const leg of firstRoute.legs) {
80
+ distance += leg.distance?.value ?? 0;
81
+ // todo 考虑用 duration_in_traffic 但这个字段上有条件的
82
+ duration += leg.duration?.value ?? 0;
83
+ }
84
+ outputRoute.path = path;
85
+ outputRoute.distance = distance;
86
+ outputRoute.duration = duration;
87
+ return;
88
+ }
89
+ case google.maps.DirectionsStatus.ZERO_RESULTS:
90
+ case google.maps.DirectionsStatus.NOT_FOUND:
91
+ outputRoute.path = [];
92
+ outputRoute.distance = 0;
93
+ outputRoute.duration = 0;
94
+ return;
95
+ default:
96
+ throw new Error(status);
97
+ }
98
+ }
99
+ );
68
100
  }
69
101
  );
70
- return pathRef;
102
+ return outputRoute;
71
103
  };
72
104
 
73
- export const useDrivingRoute = (props: UseDrivingRouteProps): ShallowRef<Point[]> => {
105
+ export const useDrivingRoute = (props: UseDrivingRouteProps): Route => {
74
106
  const { supplier } = useMapSupplier();
75
107
  return supplier === "gmap" ? useGDrivingRoute(props) : useADrivingRoute(props);
76
108
  };
@@ -5,8 +5,8 @@ export interface UseGeoLocationProps {
5
5
  onChange?: (value: { position: Point; coordinate: GeolocationCoordinates }) => any;
6
6
  onLoad?: (value: { position: Point; coordinate: GeolocationCoordinates }) => any;
7
7
  }
8
- export const useGeoLocation = (props: UseGeoLocationProps) => {
9
- const { onChange, onLoad } = props;
8
+ export const useGeoLocation = (props?: UseGeoLocationProps) => {
9
+ const { onChange, onLoad } = props ?? {};
10
10
  const loading = ref(false);
11
11
  const readyRef = ref(false);
12
12
  const errorRef = ref<GeolocationPositionError>();
@@ -0,0 +1,27 @@
1
+ import type { Point } from "../types/interface";
2
+ import { vec2lnglat } from "../utils/transform";
3
+ import { Status } from "./useMapLoader";
4
+ import { useMapSupplier } from "./useMapSupplier";
5
+
6
+ export const useAmapGeometry = () => {
7
+ const { status } = useMapSupplier();
8
+ const apiMapDistance = (from: Point, to: Point) => {
9
+ if (status !== Status.SUCCESS) return undefined;
10
+ return AMap.GeometryUtil.distance(from, to);
11
+ };
12
+ return { apiMapDistance };
13
+ };
14
+
15
+ export const useGmapGeometry = () => {
16
+ const { status } = useMapSupplier();
17
+ const apiMapDistance = (from: Point, to: Point) => {
18
+ if (status !== Status.SUCCESS) return undefined;
19
+ return google.maps.geometry.spherical.computeDistanceBetween(vec2lnglat(from), vec2lnglat(to));
20
+ };
21
+ return { apiMapDistance };
22
+ };
23
+
24
+ export const useMapGeometry = () => {
25
+ const { supplier } = useMapSupplier();
26
+ return supplier === "gmap" ? useGmapGeometry() : useAmapGeometry();
27
+ };
@@ -9,7 +9,7 @@ export const DEFAULT_AMAP_PLUGINS: AmapLoaderProps["plugins"] = [
9
9
  "AMap.Geocoder",
10
10
  "AMap.PlaceSearch",
11
11
  "AMap.Driving",
12
- "AMap.Walker",
12
+ "AMap.Walking",
13
13
  ];
14
14
  export const DEFAULT_GMAP_LIBRARIES: LoaderOptions["libraries"] = ["marker", "places", "geometry"];
15
15
 
@@ -29,6 +29,7 @@ export const useAWalkingRoute = (props: UseWalkingRouteProps) => {
29
29
  return;
30
30
  }
31
31
  case "no_data":
32
+ pathRef.value = [];
32
33
  return;
33
34
  default:
34
35
  throw result;
@@ -45,20 +46,32 @@ export const useGWalkingRoute = (props: UseWalkingRouteProps) => {
45
46
  watchPostEffectForDeepOption(
46
47
  () => ({ ...props }),
47
48
  ({ from, to }) => {
48
- gmapDirectionsService
49
- .route({
49
+ gmapDirectionsService.route(
50
+ {
50
51
  origin: { lng: from[0], lat: from[1] },
51
52
  destination: { lng: to[0], lat: to[1] },
52
53
  travelMode: google.maps.TravelMode.WALKING,
53
- })
54
- .then((result) => {
55
- let path: Point[] = [];
56
- result.routes.map((route) => {
57
- const stepPath = route.overview_path.map<Point>((item) => [item.lng(), item.lat()]);
58
- path = path.concat(stepPath);
59
- });
60
- pathRef.value = path;
61
- });
54
+ },
55
+ (result, status) => {
56
+ switch (status) {
57
+ case google.maps.DirectionsStatus.OK: {
58
+ let path: Point[] = [];
59
+ result?.routes.map((route) => {
60
+ const stepPath = route.overview_path.map<Point>((item) => [item.lng(), item.lat()]);
61
+ path = path.concat(stepPath);
62
+ });
63
+ pathRef.value = path;
64
+ return;
65
+ }
66
+ case google.maps.DirectionsStatus.ZERO_RESULTS:
67
+ case google.maps.DirectionsStatus.NOT_FOUND:
68
+ pathRef.value = [];
69
+ return;
70
+ default:
71
+ throw new Error(status);
72
+ }
73
+ }
74
+ );
62
75
  }
63
76
  );
64
77
  return pathRef;
package/src/index.ts CHANGED
@@ -20,6 +20,7 @@ export { useHeycarMap } from "./hooks/useHeycarMap";
20
20
  export { useMapAngle } from "./hooks/useMapAngle";
21
21
  export { useMapDrag } from "./hooks/useMapDrag";
22
22
  export { useMapFitView } from "./hooks/useMapFitView";
23
+ export { useMapGeometry } from "./hooks/useMapGeometry";
23
24
  export { useMapPlace } from "./hooks/useMapPlace";
24
25
  export { useMapRecomendPlace } from "./hooks/useMapRecomendPlace";
25
26
  export { useWalkingRoute } from "./hooks/useWalkingRoute";