Skip to content

Commit

Permalink
feat: change MapView API
Browse files Browse the repository at this point in the history
  • Loading branch information
Hayata Suenaga committed Aug 11, 2023
1 parent 6fcd95c commit 91a8665
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 67 deletions.
57 changes: 30 additions & 27 deletions src/MapView/MapView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {forwardRef, useEffect, useImperativeHandle, useMemo, useRef} from 'react';
import Mapbox, {MarkerView} from '@rnmapbox/maps';
import {View} from 'react-native';
import {MapViewProps, MapViewHandle} from './MapViewTypes';
import Direction from './Direction';
import {getBounds} from './utils';

const MapView = forwardRef<MapViewHandle, MapViewProps>(function MapView(
{accessToken, height, width, styleURL, pitchEnabled, mapPadding, initialState, waypoints, markerComponent: MarkerComponent, directionCoordinates},
{accessToken, style, styleURL, pitchEnabled, mapPadding, initialState, waypoints, markerComponent: MarkerComponent, directionCoordinates},
ref,
) {
const cameraRef = useRef<Mapbox.Camera>(null);
Expand Down Expand Up @@ -46,32 +47,34 @@ const MapView = forwardRef<MapViewHandle, MapViewProps>(function MapView(
}, []);

return (
<Mapbox.MapView
style={{height, width}}
styleURL={styleURL}
pitchEnabled={pitchEnabled}
>
<Mapbox.Camera
ref={cameraRef}
defaultSettings={{
centerCoordinate: initialState?.location,
zoomLevel: initialState?.zoom,
}}
bounds={bounds}
/>
{MarkerComponent &&
waypoints &&
waypoints.map((waypoint) => (
<MarkerView
id={`${waypoint[0]},${waypoint[1]}`}
key={`${waypoint[0]},${waypoint[1]}`}
coordinate={waypoint}
>
<MarkerComponent />
</MarkerView>
))}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Mapbox.MapView>
<View style={style}>
<Mapbox.MapView
styleURL={styleURL}
pitchEnabled={pitchEnabled}
style={{flex: 1}}
>
<Mapbox.Camera
ref={cameraRef}
defaultSettings={{
centerCoordinate: initialState?.location,
zoomLevel: initialState?.zoom,
}}
bounds={bounds}
/>
{MarkerComponent &&
waypoints &&
waypoints.map((waypoint) => (
<MarkerView
id={`${waypoint[0]},${waypoint[1]}`}
key={`${waypoint[0]},${waypoint[1]}`}
coordinate={waypoint}
>
<MarkerComponent />
</MarkerView>
))}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Mapbox.MapView>
</View>
);
});

Expand Down
88 changes: 55 additions & 33 deletions src/MapView/MapView.web.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,49 @@
import Map, {MapRef, Marker} from 'react-map-gl';
import {forwardRef, useImperativeHandle, useMemo, useRef} from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import {RefObject, forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react';
import WebMercatorViewport from '@math.gl/web-mercator';
import {View} from 'react-native';
import {MapViewHandle, MapViewProps} from './MapViewTypes';
import {getBounds} from './utils';
import 'mapbox-gl/dist/mapbox-gl.css';
import Direction from './Direction';
import {DEFAULT_INITIAL_STATE} from './consts';

const MapView = forwardRef<MapViewHandle, MapViewProps>(function MapView(
{accessToken, waypoints, height, width, mapPadding, markerComponent: MarkerComponent, directionCoordinates, initialState = DEFAULT_INITIAL_STATE},
{accessToken, waypoints, style, mapPadding, markerComponent: MarkerComponent, directionCoordinates, initialState = DEFAULT_INITIAL_STATE},
ref,
) {
const mapRef = useRef<MapRef>(null);
const [bounds, setBounds] = useState<{
longitude: number;
latitude: number;
zoom: number;
}>();

const bounds = useMemo(() => {
useEffect(() => {
if (!waypoints || waypoints.length === 0) {
return undefined;
return;
}

if (waypoints.length === 1) {
mapRef.current?.flyTo({
center: waypoints[0],
zoom: 15,
});
return undefined;
return;
}

const boundColors = getBounds(waypoints);
const {northEast, southWest} = getBounds(waypoints);
const {width, height} = getMapDimension(mapRef) || {
width: 0,
height: 0,
};
const viewport = new WebMercatorViewport({height, width});
return viewport.fitBounds([boundColors.northEast, boundColors.southWest], {

const {latitude, longitude, zoom} = viewport.fitBounds([southWest, northEast], {
padding: mapPadding,
});

setBounds({latitude, longitude, zoom});
}, [waypoints]);

useImperativeHandle(
Expand All @@ -47,32 +59,42 @@ const MapView = forwardRef<MapViewHandle, MapViewProps>(function MapView(
);

return (
<Map
ref={mapRef}
mapboxAccessToken={accessToken}
initialViewState={{
longitude: initialState?.location[0],
latitude: initialState?.location[1],
zoom: initialState?.zoom,
}}
style={{height, width, borderWidth: 5, borderColor: 'orange'}}
mapStyle="mapbox://styles/mapbox/streets-v9"
{...bounds}
>
{MarkerComponent &&
waypoints &&
waypoints.map((waypoint) => (
<Marker
key={`${waypoint[0]},${waypoint[1]}`}
longitude={waypoint[0]}
latitude={waypoint[1]}
>
<MarkerComponent />
</Marker>
))}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Map>
<View style={style}>
<Map
ref={mapRef}
mapboxAccessToken={accessToken}
initialViewState={{
longitude: initialState?.location[0],
latitude: initialState?.location[1],
zoom: initialState?.zoom,
}}
mapStyle="mapbox://styles/mapbox/streets-v9"
{...bounds}
>
{MarkerComponent &&
waypoints &&
waypoints.map((waypoint) => (
<Marker
key={`${waypoint[0]},${waypoint[1]}`}
longitude={waypoint[0]}
latitude={waypoint[1]}
>
<MarkerComponent />
</Marker>
))}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Map>
</View>
);
});

const getMapDimension = (mapRef: RefObject<MapRef>): {width: number; height: number} | undefined => {
if (!mapRef.current?.getMap()) {
return undefined;
}

const {clientWidth, clientHeight} = mapRef.current.getCanvas();
return {width: clientWidth, height: clientHeight};
};

export default MapView;
4 changes: 2 additions & 2 deletions src/MapView/MapViewTypes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {ComponentType} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';

export type MapViewProps = {
// Public access token to be used to fetch map data from Mapbox.
accessToken: string;
// Style applied to MapView component. Note some of the View Style props are not available on ViewMap
height: number;
width: number;
style: StyleProp<ViewStyle>;
// Link to the style JSON document.
styleURL?: string;
// Whether map can tilt in the vertical direction.
Expand Down
4 changes: 1 addition & 3 deletions src/MapView/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import {MapViewProps} from './MapViewTypes';
const DEFAULT_ZOOM = 10;
const DEFAULT_COORDINATE: [number, number] = [-122.4021, 37.7911];

// Other constants will probably defined so not using default export here
// Remove this comment once other constants are added
// eslint-disable-next-line import/prefer-default-export
export const PADDING = 50;
export const DEFAULT_INITIAL_STATE: MapViewProps['initialState'] = {
location: DEFAULT_COORDINATE,
zoom: DEFAULT_ZOOM,
Expand Down
4 changes: 2 additions & 2 deletions src/MapView/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Other util functions might be added so not using default export for this
// Remove this comment once other util functions are added
// ESLint rule forces the usage of default export if there is only one export.
// But not using default export here as more util functions might be added later.
// eslint-disable-next-line import/prefer-default-export
export const getBounds = (waypoints: Array<[number, number]>): {southWest: [number, number]; northEast: [number, number]} => {
const lngs = waypoints.map((waypoint) => waypoint[0]);
Expand Down

0 comments on commit 91a8665

Please sign in to comment.