Skip to content

Commit 5c39c3a

Browse files
authored
fix: render UserLocation when heading is 0 (#694)
1 parent 0dbe73a commit 5c39c3a

File tree

8 files changed

+120
-157
lines changed

8 files changed

+120
-157
lines changed

docs/content/components/general/heading-indicator.md

-13
This file was deleted.

docs/content/components/general/native-user-location.md

-15
This file was deleted.

docs/content/docs.json

-51
Original file line numberDiff line numberDiff line change
@@ -1281,26 +1281,6 @@
12811281
}
12821282
]
12831283
},
1284-
"HeadingIndicator": {
1285-
"description": "",
1286-
"displayName": "HeadingIndicator",
1287-
"methods": [],
1288-
"props": [
1289-
{
1290-
"name": "heading",
1291-
"required": false,
1292-
"type": "number",
1293-
"default": "none",
1294-
"description": "FIX ME NO DESCRIPTION"
1295-
}
1296-
],
1297-
"composes": [
1298-
"BaseProps"
1299-
],
1300-
"type": "component",
1301-
"filePath": "src/components/HeadingIndicator.tsx",
1302-
"name": "HeadingIndicator"
1303-
},
13041284
"HeatmapLayer": {
13051285
"description": "HeatmapLayer is a style layer that renders one or more filled circles on the map.",
13061286
"displayName": "HeatmapLayer",
@@ -2629,37 +2609,6 @@
26292609
"filePath": "src/components/MarkerView.tsx",
26302610
"name": "MarkerView"
26312611
},
2632-
"NativeUserLocation": {
2633-
"description": "",
2634-
"displayName": "NativeUserLocation",
2635-
"methods": [],
2636-
"props": [
2637-
{
2638-
"name": "androidRenderMode",
2639-
"required": false,
2640-
"type": "\"normal\" \\| \"compass\" \\| \"gps\"",
2641-
"default": "none",
2642-
"description": "Android render mode.\n\n - normal: just a circle\n - compass: triangle with heading\n - gps: large arrow\n\n@platform android"
2643-
},
2644-
{
2645-
"name": "iosShowsUserHeadingIndicator",
2646-
"required": false,
2647-
"type": "boolean",
2648-
"default": "none",
2649-
"description": "iOS only. A Boolean value indicating whether the user location annotation may display a permanent heading indicator.\n\n@platform ios"
2650-
},
2651-
{
2652-
"name": "androidPreferredFramesPerSecond",
2653-
"required": false,
2654-
"type": "number",
2655-
"default": "none",
2656-
"description": "Android only. Set max FPS at which location animators can output updates. Use this setting to limit animation rate of the location puck on higher zoom levels to decrease the stress on the device's CPU which can directly improve battery life, without sacrificing UX."
2657-
}
2658-
],
2659-
"type": "component",
2660-
"filePath": "src/components/NativeUserLocation.tsx",
2661-
"name": "NativeUserLocation"
2662-
},
26632612
"OfflineManager": {
26642613
"name": "OfflineManager",
26652614
"type": "module",

scripts/utils/DocJSONBuilder.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ const COMPONENT_DIRECTORY = path.join(WORKSPACE_ROOT, "src", "components");
1313
const MODULES_DIRECTORY = path.join(WORKSPACE_ROOT, "src", "modules");
1414
const OUTPUT_PATH = path.join(WORKSPACE_ROOT, "docs", "content", "docs.json");
1515

16+
const IGNORE_COMPONENTS = [
17+
"NativeUserLocation",
18+
"UserLocationPuck",
19+
"UserLocationPuckHeading",
20+
];
1621
const IGNORE_METHODS = ["setNativeProps"];
1722

1823
const fileExtensionsRegex = /.(js|tsx|(?<!d.)ts)$/;
@@ -365,7 +370,13 @@ export class DocJSONBuilder {
365370
}
366371

367372
async generateReactComponentsTask(results: Record<string, any>) {
368-
const filesNames = await fs.readdir(COMPONENT_DIRECTORY);
373+
const filesNames = (await fs.readdir(COMPONENT_DIRECTORY)).filter(
374+
(fileName) => {
375+
return !IGNORE_COMPONENTS.includes(path.parse(fileName).name);
376+
},
377+
);
378+
379+
console.log(filesNames);
369380

370381
const files = await Promise.all(
371382
filesNames.map(async (base) => {

src/components/HeadingIndicator.tsx

-26
This file was deleted.

src/components/UserLocation.tsx

+13-51
Original file line numberDiff line numberDiff line change
@@ -9,60 +9,14 @@ import {
99
} from "react";
1010

1111
import { Annotation } from "./Annotation";
12-
import { CircleLayer } from "./CircleLayer";
13-
import { HeadingIndicator } from "./HeadingIndicator";
1412
import { NativeUserLocation } from "./NativeUserLocation";
13+
import { UserLocationPuck } from "./UserLocationPuck";
1514
import {
1615
type Location,
1716
LocationManager,
1817
} from "../modules/location/LocationManager";
19-
import { type CircleLayerStyle } from "../types/MapLibreRNStyles";
2018

21-
const mapboxBlue = "rgba(51, 181, 229, 100)";
22-
23-
const layerStyles: Record<string, CircleLayerStyle> = {
24-
pluse: {
25-
circleRadius: 15,
26-
circleColor: mapboxBlue,
27-
circleOpacity: 0.2,
28-
circlePitchAlignment: "map",
29-
},
30-
background: {
31-
circleRadius: 9,
32-
circleColor: "#fff",
33-
circlePitchAlignment: "map",
34-
},
35-
foreground: {
36-
circleRadius: 6,
37-
circleColor: mapboxBlue,
38-
circlePitchAlignment: "map",
39-
},
40-
};
41-
42-
export const normalIcon = (
43-
showsUserHeadingIndicator?: boolean,
44-
heading?: number,
45-
) => [
46-
<CircleLayer
47-
key="mapboxUserLocationPluseCircle"
48-
id="mapboxUserLocationPluseCircle"
49-
style={layerStyles.pluse}
50-
/>,
51-
<CircleLayer
52-
key="mapboxUserLocationWhiteCircle"
53-
id="mapboxUserLocationWhiteCircle"
54-
style={layerStyles.background}
55-
/>,
56-
<CircleLayer
57-
key="mapboxUserLocationBlueCicle"
58-
id="mapboxUserLocationBlueCicle"
59-
aboveLayerID="mapboxUserLocationWhiteCircle"
60-
style={layerStyles.foreground}
61-
/>,
62-
...(showsUserHeadingIndicator && heading
63-
? [HeadingIndicator({ heading })]
64-
: []),
65-
];
19+
const USER_LOCATION_SOURCE_ID = "mlrn-user-location";
6620

6721
interface UserLocationProps {
6822
/**
@@ -290,15 +244,23 @@ export const UserLocation = memo(
290244
return (
291245
<Annotation
292246
animated={animated}
293-
id="mapboxUserLocation"
247+
id={USER_LOCATION_SOURCE_ID}
294248
onPress={onPress}
295249
coordinates={userLocationState.coordinates}
296250
style={{
297251
iconRotate: userLocationState.heading,
298252
}}
299253
>
300-
{children ||
301-
normalIcon(showsUserHeadingIndicator, userLocationState.heading)}
254+
{children || (
255+
<UserLocationPuck
256+
sourceID={USER_LOCATION_SOURCE_ID}
257+
heading={
258+
showsUserHeadingIndicator
259+
? userLocationState.heading
260+
: undefined
261+
}
262+
/>
263+
)}
302264
</Annotation>
303265
);
304266
},

src/components/UserLocationPuck.tsx

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { memo } from "react";
2+
3+
import { CircleLayer } from "./CircleLayer";
4+
import { UserLocationPuckHeading } from "./UserLocationPuckHeading";
5+
import type { BaseProps } from "../types/BaseProps";
6+
import type { CircleLayerStyle } from "../types/MapLibreRNStyles";
7+
8+
const blue = "#33B5E5";
9+
10+
const layerStyles: Record<"pulse" | "white" | "blue", CircleLayerStyle> = {
11+
pulse: {
12+
circleRadius: 15,
13+
circleColor: blue,
14+
circleOpacity: 0.2,
15+
circlePitchAlignment: "map",
16+
},
17+
white: {
18+
circleRadius: 9,
19+
circleColor: "#fff",
20+
circlePitchAlignment: "map",
21+
},
22+
blue: {
23+
circleRadius: 6,
24+
circleColor: blue,
25+
circlePitchAlignment: "map",
26+
},
27+
};
28+
29+
interface UserLocationPuckProps extends BaseProps {
30+
sourceID: string;
31+
heading?: number;
32+
belowLayerID?: string;
33+
}
34+
35+
export const UserLocationPuck = memo(
36+
({ sourceID, heading }: UserLocationPuckProps) => (
37+
<>
38+
<CircleLayer
39+
id="mlrn-user-location-puck-pulse"
40+
sourceID={sourceID}
41+
style={layerStyles.pulse}
42+
/>
43+
<CircleLayer
44+
id="mlrn-user-location-puck-white"
45+
sourceID={sourceID}
46+
style={layerStyles.white}
47+
/>
48+
<CircleLayer
49+
id="mlrn-user-location-puck-blue"
50+
sourceID={sourceID}
51+
style={layerStyles.blue}
52+
/>
53+
{typeof heading === "number" && (
54+
<UserLocationPuckHeading
55+
sourceID={sourceID}
56+
belowLayerID="mlrn-user-location-puck-white"
57+
heading={heading}
58+
/>
59+
)}
60+
</>
61+
),
62+
);
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { memo } from "react";
2+
3+
import { SymbolLayer } from "./SymbolLayer";
4+
import headingIcon from "../assets/heading.png";
5+
import { type BaseProps } from "../types/BaseProps";
6+
import type { SymbolLayerStyle } from "../types/MapLibreRNStyles";
7+
8+
const layerStyle: SymbolLayerStyle = {
9+
iconImage: headingIcon,
10+
iconAllowOverlap: true,
11+
iconPitchAlignment: "map",
12+
iconRotationAlignment: "map",
13+
};
14+
15+
interface UserLocationPuckHeadingProps extends BaseProps {
16+
sourceID: string;
17+
belowLayerID?: string;
18+
heading: number;
19+
}
20+
21+
export const UserLocationPuckHeading = memo(
22+
({ sourceID, belowLayerID, heading }: UserLocationPuckHeadingProps) => (
23+
<SymbolLayer
24+
id="mlrn-user-location-puck-heading"
25+
sourceID={sourceID}
26+
belowLayerID={belowLayerID}
27+
style={{
28+
iconRotate: heading,
29+
...layerStyle,
30+
}}
31+
/>
32+
),
33+
);

0 commit comments

Comments
 (0)