|
|
@@ -436,6 +436,8 @@ const SERIES_TEXT_SIZE = [
|
|
|
15
|
|
|
] as unknown as number;
|
|
|
|
|
|
+const processedSeriesShares = new Set<number>();
|
|
|
+
|
|
|
const MapScreen: any = ({ navigation, route }: { navigation: any; route: any }) => {
|
|
|
const tabBarHeight = useBottomTabBarHeight();
|
|
|
const userId = storage.get('uid', StoreType.STRING) as string;
|
|
|
@@ -585,6 +587,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
const [renderCamera, setRenderCamera] = useState(Platform.OS === 'ios');
|
|
|
const isAnimatingRef = useRef(false);
|
|
|
const animationTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
+ const handledSeriesShareRef = useRef<number | null>(null);
|
|
|
|
|
|
const [markerCoords, setMarkerCoords] = useState<any>(null);
|
|
|
const [refreshInterval, setRefreshInterval] = useState(0);
|
|
|
@@ -997,7 +1000,16 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
|
|
|
return () => clearTimeout(timeoutId);
|
|
|
}
|
|
|
- if (route.params?.id && route.params?.type && db1 && db2 && db3) {
|
|
|
+ if (route.params?.seriesItemShare) {
|
|
|
+ const itemToFind = route.params.seriesItemShare;
|
|
|
+ const shareId = itemToFind._timestamp || itemToFind.item_id;
|
|
|
+ if (!processedSeriesShares.has(shareId)) {
|
|
|
+ processedSeriesShares.add(shareId);
|
|
|
+ handledSeriesShareRef.current = shareId;
|
|
|
+ navigation.setParams({ seriesItemShare: undefined });
|
|
|
+ handleFindSeries(itemToFind);
|
|
|
+ }
|
|
|
+ } else if (route.params?.id && route.params?.type && db1 && db2 && db3) {
|
|
|
handleFindRegion(route.params?.id, route.params?.type);
|
|
|
}
|
|
|
}, [route, db1, db2, db3]);
|
|
|
@@ -1007,6 +1019,11 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
if (token) {
|
|
|
refetch();
|
|
|
}
|
|
|
+ return () => {
|
|
|
+ if (handledSeriesShareRef.current !== null) {
|
|
|
+ setSelectedMarker(null);
|
|
|
+ }
|
|
|
+ };
|
|
|
}, [])
|
|
|
);
|
|
|
|
|
|
@@ -1818,7 +1835,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
try {
|
|
|
if (seriesItem.location_geojson) {
|
|
|
const geojsonObj = JSON.parse(seriesItem.location_geojson);
|
|
|
-
|
|
|
+
|
|
|
if (geojsonObj.type === 'Point') {
|
|
|
const parsedCoords = geojsonObj.coordinates;
|
|
|
if (parsedCoords && parsedCoords.length === 2) {
|
|
|
@@ -1861,17 +1878,21 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
}
|
|
|
|
|
|
if (coordinates) {
|
|
|
- cameraController.setCamera({
|
|
|
- centerCoordinate: coordinates,
|
|
|
- zoomLevel: 10,
|
|
|
- animationDuration: 1000,
|
|
|
- animationMode: 'flyTo'
|
|
|
- });
|
|
|
+ setTimeout(() => {
|
|
|
+ cameraController.setCamera({
|
|
|
+ centerCoordinate: coordinates,
|
|
|
+ zoomLevel: 10,
|
|
|
+ animationDuration: 1000,
|
|
|
+ animationMode: 'flyTo'
|
|
|
+ });
|
|
|
+ }, 800);
|
|
|
+
|
|
|
+ handledSeriesShareRef.current = seriesItem.item_id;
|
|
|
|
|
|
setSelectedMarker({
|
|
|
coordinates,
|
|
|
name: seriesItem.item_name,
|
|
|
- icon: { uri: API_HOST + seriesItem.series_icon },
|
|
|
+ icon: seriesItem.series_icon ? { uri: API_HOST + seriesItem.series_icon } : null,
|
|
|
description: seriesItem.series_name,
|
|
|
series_name: seriesItem.series_name,
|
|
|
visited: seriesItem.visited,
|
|
|
@@ -1886,7 +1907,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
try {
|
|
|
if (!mapRef.current) return;
|
|
|
const pointInView = await mapRef.current.getPointInView(coordinates);
|
|
|
-
|
|
|
+
|
|
|
if (pointInView) {
|
|
|
const { features } = await mapRef.current.queryRenderedFeaturesAtPoint(
|
|
|
pointInView,
|
|
|
@@ -1970,7 +1991,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
return {
|
|
|
coordinates,
|
|
|
name,
|
|
|
- icon,
|
|
|
+ icon: icon || (isSameMarker ? prev.icon : null),
|
|
|
description,
|
|
|
series_name,
|
|
|
visited: currentVisited,
|
|
|
@@ -2444,210 +2465,210 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
>
|
|
|
{seriesFilter.status !== 1
|
|
|
? (() => {
|
|
|
- try {
|
|
|
- return [
|
|
|
- <MapLibreRN.SymbolLayer
|
|
|
- key="symbol_unvisited_normal"
|
|
|
- id={`${series_layer.id}_normal`}
|
|
|
- sourceID={series_layer.source}
|
|
|
- sourceLayerID={series_layer['source-layer']}
|
|
|
- aboveLayerID={'waterway-name'}
|
|
|
- filter={['all', seriesNotVisitedFilter, ['!=', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_layer.minzoom}
|
|
|
- maxZoomLevel={series_layer.maxzoom}
|
|
|
- style={{
|
|
|
- symbolSpacing: 1,
|
|
|
- iconImage: '{series_id}',
|
|
|
- iconAllowOverlap: true,
|
|
|
- iconIgnorePlacement: true,
|
|
|
- iconSize: SERIES_ICON_SIZE,
|
|
|
- visibility: 'visible',
|
|
|
- iconColor: '#666',
|
|
|
- iconOpacity: 1,
|
|
|
- iconHaloColor: '#ffffff',
|
|
|
- iconHaloWidth: 1,
|
|
|
- iconHaloBlur: 0.5,
|
|
|
- textAnchor: 'top',
|
|
|
- textField: seriesTextField,
|
|
|
- textFont: ['Noto Sans Regular'],
|
|
|
- textMaxWidth: 9,
|
|
|
- textOffset: [0, 1.3],
|
|
|
- textPadding: 2,
|
|
|
- textSize: SERIES_TEXT_SIZE,
|
|
|
- textOptional: true,
|
|
|
- textIgnorePlacement: false,
|
|
|
- textAllowOverlap: false,
|
|
|
- textColor: '#666',
|
|
|
- textHaloColor: '#ffffff',
|
|
|
- textHaloWidth: 1,
|
|
|
- textHaloBlur: 0.5
|
|
|
- }}
|
|
|
- />,
|
|
|
- <MapLibreRN.CircleLayer
|
|
|
- key="circle_unvisited_must"
|
|
|
- id={`${series_layer.id}_must_wrapper`}
|
|
|
- sourceID={series_layer.source}
|
|
|
- sourceLayerID={series_layer['source-layer']}
|
|
|
- aboveLayerID={`${series_layer.id}_normal`}
|
|
|
- filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_layer.minzoom}
|
|
|
- maxZoomLevel={series_layer.maxzoom}
|
|
|
- style={{
|
|
|
- circleRadius: SERIES_CIRCLE_RADIUS,
|
|
|
- circleColor: Colors.ORANGE,
|
|
|
- circleOpacity: 1,
|
|
|
- circleStrokeWidth: SERIES_CIRCLE_STROKE,
|
|
|
- circleStrokeColor: Colors.ORANGE,
|
|
|
- visibility: 'visible'
|
|
|
- }}
|
|
|
- />,
|
|
|
- <MapLibreRN.SymbolLayer
|
|
|
- key="symbol_unvisited_must"
|
|
|
- id={series_layer.id}
|
|
|
- sourceID={series_layer.source}
|
|
|
- sourceLayerID={series_layer['source-layer']}
|
|
|
- aboveLayerID={`${series_layer.id}_must_wrapper`}
|
|
|
- filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_layer.minzoom}
|
|
|
- maxZoomLevel={series_layer.maxzoom}
|
|
|
- style={{
|
|
|
- symbolSpacing: 1,
|
|
|
- iconImage: '{series_id}',
|
|
|
- iconAllowOverlap: true,
|
|
|
- iconIgnorePlacement: true,
|
|
|
- iconSize: SERIES_ICON_SIZE,
|
|
|
- visibility: 'visible',
|
|
|
- iconColor: '#666',
|
|
|
- iconOpacity: 1,
|
|
|
- iconHaloColor: '#ffffff',
|
|
|
- iconHaloWidth: 1,
|
|
|
- iconHaloBlur: 0.5,
|
|
|
- textAnchor: 'top',
|
|
|
- textField: seriesTextField,
|
|
|
- textFont: ['Noto Sans Regular'],
|
|
|
- textMaxWidth: 9,
|
|
|
- textOffset: [0, 1.3],
|
|
|
- textPadding: 2,
|
|
|
- textSize: SERIES_TEXT_SIZE,
|
|
|
- textOptional: true,
|
|
|
- textIgnorePlacement: false,
|
|
|
- textAllowOverlap: false,
|
|
|
- textColor: '#666',
|
|
|
- textHaloColor: '#ffffff',
|
|
|
- textHaloWidth: 1,
|
|
|
- textHaloBlur: 0.5
|
|
|
- }}
|
|
|
- />
|
|
|
- ];
|
|
|
- } catch (error) {
|
|
|
- console.warn('SymbolLayer render error:', error);
|
|
|
- return null;
|
|
|
- }
|
|
|
- })()
|
|
|
+ try {
|
|
|
+ return [
|
|
|
+ <MapLibreRN.SymbolLayer
|
|
|
+ key="symbol_unvisited_normal"
|
|
|
+ id={`${series_layer.id}_normal`}
|
|
|
+ sourceID={series_layer.source}
|
|
|
+ sourceLayerID={series_layer['source-layer']}
|
|
|
+ aboveLayerID={'waterway-name'}
|
|
|
+ filter={['all', seriesNotVisitedFilter, ['!=', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_layer.minzoom}
|
|
|
+ maxZoomLevel={series_layer.maxzoom}
|
|
|
+ style={{
|
|
|
+ symbolSpacing: 1,
|
|
|
+ iconImage: '{series_id}',
|
|
|
+ iconAllowOverlap: true,
|
|
|
+ iconIgnorePlacement: true,
|
|
|
+ iconSize: SERIES_ICON_SIZE,
|
|
|
+ visibility: 'visible',
|
|
|
+ iconColor: '#666',
|
|
|
+ iconOpacity: 1,
|
|
|
+ iconHaloColor: '#ffffff',
|
|
|
+ iconHaloWidth: 1,
|
|
|
+ iconHaloBlur: 0.5,
|
|
|
+ textAnchor: 'top',
|
|
|
+ textField: seriesTextField,
|
|
|
+ textFont: ['Noto Sans Regular'],
|
|
|
+ textMaxWidth: 9,
|
|
|
+ textOffset: [0, 1.3],
|
|
|
+ textPadding: 2,
|
|
|
+ textSize: SERIES_TEXT_SIZE,
|
|
|
+ textOptional: true,
|
|
|
+ textIgnorePlacement: false,
|
|
|
+ textAllowOverlap: false,
|
|
|
+ textColor: '#666',
|
|
|
+ textHaloColor: '#ffffff',
|
|
|
+ textHaloWidth: 1,
|
|
|
+ textHaloBlur: 0.5
|
|
|
+ }}
|
|
|
+ />,
|
|
|
+ <MapLibreRN.CircleLayer
|
|
|
+ key="circle_unvisited_must"
|
|
|
+ id={`${series_layer.id}_must_wrapper`}
|
|
|
+ sourceID={series_layer.source}
|
|
|
+ sourceLayerID={series_layer['source-layer']}
|
|
|
+ aboveLayerID={`${series_layer.id}_normal`}
|
|
|
+ filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_layer.minzoom}
|
|
|
+ maxZoomLevel={series_layer.maxzoom}
|
|
|
+ style={{
|
|
|
+ circleRadius: SERIES_CIRCLE_RADIUS,
|
|
|
+ circleColor: Colors.ORANGE,
|
|
|
+ circleOpacity: 1,
|
|
|
+ circleStrokeWidth: SERIES_CIRCLE_STROKE,
|
|
|
+ circleStrokeColor: Colors.ORANGE,
|
|
|
+ visibility: 'visible'
|
|
|
+ }}
|
|
|
+ />,
|
|
|
+ <MapLibreRN.SymbolLayer
|
|
|
+ key="symbol_unvisited_must"
|
|
|
+ id={series_layer.id}
|
|
|
+ sourceID={series_layer.source}
|
|
|
+ sourceLayerID={series_layer['source-layer']}
|
|
|
+ aboveLayerID={`${series_layer.id}_must_wrapper`}
|
|
|
+ filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_layer.minzoom}
|
|
|
+ maxZoomLevel={series_layer.maxzoom}
|
|
|
+ style={{
|
|
|
+ symbolSpacing: 1,
|
|
|
+ iconImage: '{series_id}',
|
|
|
+ iconAllowOverlap: true,
|
|
|
+ iconIgnorePlacement: true,
|
|
|
+ iconSize: SERIES_ICON_SIZE,
|
|
|
+ visibility: 'visible',
|
|
|
+ iconColor: '#666',
|
|
|
+ iconOpacity: 1,
|
|
|
+ iconHaloColor: '#ffffff',
|
|
|
+ iconHaloWidth: 1,
|
|
|
+ iconHaloBlur: 0.5,
|
|
|
+ textAnchor: 'top',
|
|
|
+ textField: seriesTextField,
|
|
|
+ textFont: ['Noto Sans Regular'],
|
|
|
+ textMaxWidth: 9,
|
|
|
+ textOffset: [0, 1.3],
|
|
|
+ textPadding: 2,
|
|
|
+ textSize: SERIES_TEXT_SIZE,
|
|
|
+ textOptional: true,
|
|
|
+ textIgnorePlacement: false,
|
|
|
+ textAllowOverlap: false,
|
|
|
+ textColor: '#666',
|
|
|
+ textHaloColor: '#ffffff',
|
|
|
+ textHaloWidth: 1,
|
|
|
+ textHaloBlur: 0.5
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ];
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('SymbolLayer render error:', error);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ })()
|
|
|
: null}
|
|
|
|
|
|
{seriesFilter.status !== 0
|
|
|
? (() => {
|
|
|
- try {
|
|
|
- return [
|
|
|
- <MapLibreRN.SymbolLayer
|
|
|
- key="symbol_visited_normal"
|
|
|
- id={`${series_visited.id}_normal`}
|
|
|
- sourceID={series_visited.source}
|
|
|
- sourceLayerID={series_visited['source-layer']}
|
|
|
- aboveLayerID={'waterway-name'}
|
|
|
- filter={['all', seriesVisitedFilter, ['!=', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_visited.minzoom}
|
|
|
- maxZoomLevel={series_visited.maxzoom}
|
|
|
- style={{
|
|
|
- symbolSpacing: 1,
|
|
|
- iconImage: '{series_id}v',
|
|
|
- iconAllowOverlap: true,
|
|
|
- iconIgnorePlacement: true,
|
|
|
- iconSize: SERIES_ICON_SIZE,
|
|
|
- visibility: 'visible',
|
|
|
- iconColor: '#666',
|
|
|
- iconOpacity: 1,
|
|
|
- iconHaloColor: '#ffffff',
|
|
|
- iconHaloWidth: 1,
|
|
|
- iconHaloBlur: 0.5,
|
|
|
- textAnchor: 'top',
|
|
|
- textField: seriesTextField,
|
|
|
- textFont: ['Noto Sans Regular'],
|
|
|
- textMaxWidth: 9,
|
|
|
- textOffset: [0, 1.3],
|
|
|
- textPadding: 2,
|
|
|
- textSize: SERIES_TEXT_SIZE,
|
|
|
- textOptional: true,
|
|
|
- textIgnorePlacement: false,
|
|
|
- textAllowOverlap: false,
|
|
|
- textColor: '#666',
|
|
|
- textHaloColor: '#ffffff',
|
|
|
- textHaloWidth: 1,
|
|
|
- textHaloBlur: 0.5
|
|
|
- }}
|
|
|
- />,
|
|
|
- <MapLibreRN.CircleLayer
|
|
|
- key="circle_visited_must"
|
|
|
- id={`${series_visited.id}_must_wrapper`}
|
|
|
- sourceID={series_visited.source}
|
|
|
- sourceLayerID={series_visited['source-layer']}
|
|
|
- aboveLayerID={`${series_visited.id}_normal`}
|
|
|
- filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_visited.minzoom}
|
|
|
- maxZoomLevel={series_visited.maxzoom}
|
|
|
- style={{
|
|
|
- circleRadius: SERIES_CIRCLE_RADIUS,
|
|
|
- circleColor: Colors.ORANGE,
|
|
|
- circleOpacity: 1,
|
|
|
- circleStrokeWidth: SERIES_CIRCLE_STROKE,
|
|
|
- circleStrokeColor: Colors.ORANGE,
|
|
|
- visibility: 'visible'
|
|
|
- }}
|
|
|
- />,
|
|
|
- <MapLibreRN.SymbolLayer
|
|
|
- key="symbol_visited_must"
|
|
|
- id={series_visited.id}
|
|
|
- sourceID={series_visited.source}
|
|
|
- sourceLayerID={series_visited['source-layer']}
|
|
|
- aboveLayerID={`${series_visited.id}_must_wrapper`}
|
|
|
- filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
- minZoomLevel={series_visited.minzoom}
|
|
|
- maxZoomLevel={series_visited.maxzoom}
|
|
|
- style={{
|
|
|
- symbolSpacing: 1,
|
|
|
- iconImage: '{series_id}v',
|
|
|
- iconAllowOverlap: true,
|
|
|
- iconIgnorePlacement: true,
|
|
|
- iconSize: SERIES_ICON_SIZE,
|
|
|
- visibility: 'visible',
|
|
|
- iconColor: '#666',
|
|
|
- iconOpacity: 1,
|
|
|
- iconHaloColor: '#ffffff',
|
|
|
- iconHaloWidth: 1,
|
|
|
- iconHaloBlur: 0.5,
|
|
|
- textAnchor: 'top',
|
|
|
- textField: seriesTextField,
|
|
|
- textFont: ['Noto Sans Regular'],
|
|
|
- textMaxWidth: 9,
|
|
|
- textOffset: [0, 1.3],
|
|
|
- textPadding: 2,
|
|
|
- textSize: SERIES_TEXT_SIZE,
|
|
|
- textOptional: true,
|
|
|
- textIgnorePlacement: false,
|
|
|
- textAllowOverlap: false,
|
|
|
- textColor: '#666',
|
|
|
- textHaloColor: '#ffffff',
|
|
|
- textHaloWidth: 1,
|
|
|
- textHaloBlur: 0.5
|
|
|
- }}
|
|
|
- />
|
|
|
- ];
|
|
|
- } catch (error) {
|
|
|
- console.warn('SymbolLayer render error:', error);
|
|
|
- return null;
|
|
|
- }
|
|
|
- })()
|
|
|
+ try {
|
|
|
+ return [
|
|
|
+ <MapLibreRN.SymbolLayer
|
|
|
+ key="symbol_visited_normal"
|
|
|
+ id={`${series_visited.id}_normal`}
|
|
|
+ sourceID={series_visited.source}
|
|
|
+ sourceLayerID={series_visited['source-layer']}
|
|
|
+ aboveLayerID={'waterway-name'}
|
|
|
+ filter={['all', seriesVisitedFilter, ['!=', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_visited.minzoom}
|
|
|
+ maxZoomLevel={series_visited.maxzoom}
|
|
|
+ style={{
|
|
|
+ symbolSpacing: 1,
|
|
|
+ iconImage: '{series_id}v',
|
|
|
+ iconAllowOverlap: true,
|
|
|
+ iconIgnorePlacement: true,
|
|
|
+ iconSize: SERIES_ICON_SIZE,
|
|
|
+ visibility: 'visible',
|
|
|
+ iconColor: '#666',
|
|
|
+ iconOpacity: 1,
|
|
|
+ iconHaloColor: '#ffffff',
|
|
|
+ iconHaloWidth: 1,
|
|
|
+ iconHaloBlur: 0.5,
|
|
|
+ textAnchor: 'top',
|
|
|
+ textField: seriesTextField,
|
|
|
+ textFont: ['Noto Sans Regular'],
|
|
|
+ textMaxWidth: 9,
|
|
|
+ textOffset: [0, 1.3],
|
|
|
+ textPadding: 2,
|
|
|
+ textSize: SERIES_TEXT_SIZE,
|
|
|
+ textOptional: true,
|
|
|
+ textIgnorePlacement: false,
|
|
|
+ textAllowOverlap: false,
|
|
|
+ textColor: '#666',
|
|
|
+ textHaloColor: '#ffffff',
|
|
|
+ textHaloWidth: 1,
|
|
|
+ textHaloBlur: 0.5
|
|
|
+ }}
|
|
|
+ />,
|
|
|
+ <MapLibreRN.CircleLayer
|
|
|
+ key="circle_visited_must"
|
|
|
+ id={`${series_visited.id}_must_wrapper`}
|
|
|
+ sourceID={series_visited.source}
|
|
|
+ sourceLayerID={series_visited['source-layer']}
|
|
|
+ aboveLayerID={`${series_visited.id}_normal`}
|
|
|
+ filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_visited.minzoom}
|
|
|
+ maxZoomLevel={series_visited.maxzoom}
|
|
|
+ style={{
|
|
|
+ circleRadius: SERIES_CIRCLE_RADIUS,
|
|
|
+ circleColor: Colors.ORANGE,
|
|
|
+ circleOpacity: 1,
|
|
|
+ circleStrokeWidth: SERIES_CIRCLE_STROKE,
|
|
|
+ circleStrokeColor: Colors.ORANGE,
|
|
|
+ visibility: 'visible'
|
|
|
+ }}
|
|
|
+ />,
|
|
|
+ <MapLibreRN.SymbolLayer
|
|
|
+ key="symbol_visited_must"
|
|
|
+ id={series_visited.id}
|
|
|
+ sourceID={series_visited.source}
|
|
|
+ sourceLayerID={series_visited['source-layer']}
|
|
|
+ aboveLayerID={`${series_visited.id}_must_wrapper`}
|
|
|
+ filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
|
|
|
+ minZoomLevel={series_visited.minzoom}
|
|
|
+ maxZoomLevel={series_visited.maxzoom}
|
|
|
+ style={{
|
|
|
+ symbolSpacing: 1,
|
|
|
+ iconImage: '{series_id}v',
|
|
|
+ iconAllowOverlap: true,
|
|
|
+ iconIgnorePlacement: true,
|
|
|
+ iconSize: SERIES_ICON_SIZE,
|
|
|
+ visibility: 'visible',
|
|
|
+ iconColor: '#666',
|
|
|
+ iconOpacity: 1,
|
|
|
+ iconHaloColor: '#ffffff',
|
|
|
+ iconHaloWidth: 1,
|
|
|
+ iconHaloBlur: 0.5,
|
|
|
+ textAnchor: 'top',
|
|
|
+ textField: seriesTextField,
|
|
|
+ textFont: ['Noto Sans Regular'],
|
|
|
+ textMaxWidth: 9,
|
|
|
+ textOffset: [0, 1.3],
|
|
|
+ textPadding: 2,
|
|
|
+ textSize: SERIES_TEXT_SIZE,
|
|
|
+ textOptional: true,
|
|
|
+ textIgnorePlacement: false,
|
|
|
+ textAllowOverlap: false,
|
|
|
+ textColor: '#666',
|
|
|
+ textHaloColor: '#ffffff',
|
|
|
+ textHaloWidth: 1,
|
|
|
+ textHaloBlur: 0.5
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ];
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('SymbolLayer render error:', error);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ })()
|
|
|
: null}
|
|
|
</MapLibreRN.VectorSource>
|
|
|
|