Skip to content

Commit

Permalink
feat(web): MarkerView POC (#3486)
Browse files Browse the repository at this point in the history
* Implemented web MarkerView poc

* feat(web): added web example for marker view

---------

Co-authored-by: Volker Lieber <[email protected]>
  • Loading branch information
mfazekas and VolkerLieber authored May 12, 2024
1 parent 18bc6d8 commit 460110a
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 15 deletions.
10 changes: 10 additions & 0 deletions example/src/examples/Animations/AnimatedLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,13 @@ class AnimatedLine extends React.Component {
}

export default AnimatedLine;

/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'Animated Line',
tags: [],
docs: `
Animated Line
`,
};
AnimatedLine.metadata = metadata;
12 changes: 12 additions & 0 deletions example/src/examples/Animations/AnimatedLineOffsets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { lineString } from '@turf/helpers';
import bbox from '@turf/bbox';
import length from '@turf/length';

import type { ExampleWithMetadata } from '../common/ExampleMetadata';

Logger.setLogLevel('verbose');

const baseCoordinates: Position[] = [
Expand Down Expand Up @@ -251,3 +253,13 @@ const AnimatedLineOffsets = memo(() => {
});

export default AnimatedLineOffsets;

/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'Animated Line Offset',
tags: [],
docs: `
Animated Line Offsets (Native Animator)
`,
};
(AnimatedLineOffsets as unknown as ExampleWithMetadata).metadata = metadata;
12 changes: 12 additions & 0 deletions example/src/examples/Animations/AnimatedPoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { Divider, Slider, Text } from '@rneui/base';
import { SafeAreaView } from 'react-native-safe-area-context';
import { View, Button, StyleProp, ViewStyle } from 'react-native';

import type { ExampleWithMetadata } from '../common/ExampleMetadata';

Logger.setLogLevel('verbose');

const basePosition: Position = [-83.53808787278204, 41.66430343748789];
Expand Down Expand Up @@ -138,3 +140,13 @@ const AnimatedPoint = memo(() => {
});

export default AnimatedPoint;

/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'Animaated point',
tags: [],
docs: `
Animated Point (Native Animator)
`,
};
(AnimatedPoint as unknown as ExampleWithMetadata).metadata = metadata;
10 changes: 10 additions & 0 deletions example/src/examples/Animations/DriveTheLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,13 @@ class DriveTheLine extends React.Component {
}

export default DriveTheLine;

/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'Animated Point Along a Line',
tags: [],
docs: `
Shows animation of a point along a line-layer
`,
};
DriveTheLine.metadata = metadata;
8 changes: 8 additions & 0 deletions example/src/examples/Animations/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export { default as AnimatedLine } from './AnimatedLine';
export { default as AnimatedLineOffsets } from './AnimatedLineOffsets';
export { default as AnimatedPoint } from './AnimatedPoint';
export { default as DriveTheLine } from './DriveTheLine';

export const metadata = {
title: 'Animations',
};
30 changes: 30 additions & 0 deletions example/src/examples/Web/MarkerView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { View, Text } from 'react-native';
import { MapView, Camera, MarkerView } from '@rnmapbox/maps';

function MarkerViewExample() {
return (
<MapView style={{ flex: 1 }}>
<Camera zoomLevel={9} centerCoordinate={[-73.970895, 40.723279]} />
<MarkerView coordinate={[-73.970895, 40.723279]}>
<View style={{ backgroundColor: 'red', padding: 8 }}>
<Text>Hello</Text>
</View>
</MarkerView>
</MapView>
);
}

export default MarkerViewExample;

/* end-example-doc */

/** @type ExampleWithMetadata['metadata'] */
const metadata = {
title: 'MarkerView',
tags: ['MarkerView'],
docs: `
Shows MarkerView
`,
};
MarkerViewExample.metadata = metadata;
5 changes: 5 additions & 0 deletions example/src/examples/Web/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { default as MarkerView } from './MarkerView';

export const metadata = {
title: 'Web',
};
18 changes: 5 additions & 13 deletions example/src/scenes/GroupAndItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import MapHeader from '../examples/common/MapHeader';
import Page, { PageProps } from '../examples/common/Page';
import sheet from '../styles/sheet';
// ANIMATIONS
import AnimatedPoint from '../examples/Animations/AnimatedPoint';
import AnimatedLineOffsets from '../examples/Animations/AnimatedLineOffsets';
import AnimatedLine from '../examples/Animations/AnimatedLine';
import DriveTheLine from '../examples/Animations/DriveTheLine';
import * as Animations from '../examples/Animations';
// ANNOTATIONS
import * as Annotations from '../examples/Annotations';
// CAMERA
Expand All @@ -33,6 +30,8 @@ import * as Map from '../examples/Map';
import * as SymbolCircleLayer from '../examples/SymbolCircleLayer';
// USERLOCATION
import * as UserLocation from '../examples/UserLocation';
// WEB
import * as Web from '../examples/Web';
// MISC
import BugReportExample from '../examples/BugReportExample';
import BugReportExampleTS from '../examples/BugReportExampleTS';
Expand Down Expand Up @@ -298,15 +297,8 @@ const Examples = new ExampleGroup('React Native Mapbox', [
exampleGroup(FillRasterLayer),
exampleGroup(LineLayer),
exampleGroup(Annotations),
new ExampleGroup('Animations', [
new ExampleItem('Animated Point (Native Animator)', AnimatedPoint),
new ExampleItem(
'Animated Line Offsets (Native Animator)',
AnimatedLineOffsets,
),
new ExampleItem('Animated Line', AnimatedLine),
new ExampleItem('Animated Point Along a Line', DriveTheLine),
]),
exampleGroup(Animations),
exampleGroup(Web),
new ExampleItem('Cache management', CacheManagement),
]);

Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@
"expo": ">=47.0.0",
"mapbox-gl": "^2.9.0",
"react": ">=16.6.1",
"react-native": ">=0.59.9"
"react-native": ">=0.59.9",
"react-dom": ">= 17.0.0"
},
"peerDependenciesMeta": {
"expo": {
"optional": true
},
"mapbox-gl": {
"optional": true
},
"react-dom": {
"optional": true
}
},
"dependencies": {
Expand Down
77 changes: 77 additions & 0 deletions src/web/components/MarkerView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Marker } from 'mapbox-gl';
import {
forwardRef,
isValidElement,
memo,
ReactElement,
Ref,
useContext,
useEffect,
useImperativeHandle,
useMemo,
} from 'react';
import { createPortal } from 'react-dom';

import MapContext from '../MapContext';

type MarkerViewProps = {
coordinate: [number, number];
children?: ReactElement;
};

function MarkerView(props: MarkerViewProps, ref: Ref<Marker>) {
const { map } = useContext(MapContext);

// Create marker instance
const marker: Marker = useMemo(() => {
const _marker = new Marker({
element: isValidElement(props.children)
? document.createElement('div')
: undefined,
});

// Set marker coordinates
_marker.setLngLat(props.coordinate);

// Fix marker position
const { style } = marker.getElement();
style.position = 'absolute';
style.top = '0';
style.left = '0';

return _marker;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// Add marker to map
useEffect(() => {
if (map === undefined) {
return;
}

marker.addTo(map);

return () => {
marker.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [map]);

// Expose marker instance
// eslint-disable-next-line react-hooks/exhaustive-deps
useImperativeHandle(ref, () => marker, []);

// Update marker coordinates
const markerCoordinate = marker.getLngLat();
if (
markerCoordinate.lng !== props.coordinate[0] ||
markerCoordinate.lat !== props.coordinate[1]
) {
marker.setLngLat([props.coordinate[0], props.coordinate[1]]);
}

// Inject children into marker element
return createPortal(props.children, marker.getElement());
}

export default memo(forwardRef(MarkerView));
4 changes: 3 additions & 1 deletion src/web/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import MapboxModule from './MapboxModule';
import Camera from './components/Camera';
import MapView from './components/MapView';
import MarkerView from './components/MarkerView';
import Logger from './utils/Logger';

const ExportedComponents = {
Camera,
MapView,
Logger,
MarkerView,
};

const Mapbox = {
...MapboxModule,
...ExportedComponents,
};

export { Camera, MapView, Logger };
export { Camera, Logger, MapView, MarkerView };
export default Mapbox;

0 comments on commit 460110a

Please sign in to comment.