Skip to content

Commit

Permalink
feat(Layer): introduce onEnter and onLeave props
Browse files Browse the repository at this point in the history
  • Loading branch information
stepankuzmin committed Oct 19, 2017
1 parent 348cbcb commit 684cb05
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 46 deletions.
80 changes: 80 additions & 0 deletions docs/another-hoverable-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
```jsx
const Immutable = require('immutable');
const random = require('@turf/random');

const points = random('points', 10);
points.features.forEach((feature, index) => {
feature.properties.id = index;
});

initialState = {
sources: Immutable.fromJS({
markers: {
type: 'geojson',
data: points
}
}),
layers: Immutable.fromJS({
markers: {
id: 'markers',
type: 'circle',
source: 'markers',
paint: {
'circle-radius': 16,
'circle-color': '#1978c8'
}
},
'highlighted-marker': {
id: 'highlighted-marker',
type: 'circle',
source: 'markers',
paint: {
'circle-radius': 16,
'circle-color': '#f28a25'
},
filter: ['==', 'id', '']
}
}),
viewport: {
latitude: 0,
longitude: 0,
zoom: 0
}
};

const onEnter = (event) => {
const feature = event.features[0];
if (!feature) return;

const newLayers = state.layers.setIn(
['highlighted-marker', 'filter', 2],
feature.properties.id
);

setState({ layers: newLayers });
};

const onLeave = (event) => {
const newLayers = state.layers.setIn(
['highlighted-marker', 'filter', 2],
''
);

setState({ layers: newLayers });
};

<MapGL
style={{ width: "100%", height: "400px" }}
mapStyle="mapbox://styles/mapbox/light-v9"
accessToken={MAPBOX_ACCESS_TOKEN}
{...state.viewport}
>
<Source id='markers' source={state.sources.get('markers')} />
<Layer
onEnter={onEnter}
onLeave={onLeave}
layer={state.layers.get('markers')}
/>
<Layer layer={state.layers.get('highlighted-marker')} />
</MapGL>
```
26 changes: 10 additions & 16 deletions docs/clickable-map.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
```jsx
const Immutable = require('immutable');
const random = require('@turf/random');

const points = random('points', 10);
points.features.forEach((feature, index) => {
feature.properties.id = index;
});

initialState = {
mapStyle: Immutable.fromJS({
version: 8,
sources: {},
layers: []
}),
sources: Immutable.fromJS({
markers: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{ type: 'Feature', properties: { id: 1 }, geometry: { type: 'Point', coordinates: [0, 20] } },
{ type: 'Feature', properties: { id: 2 }, geometry: { type: 'Point', coordinates: [-20, 0] } },
{ type: 'Feature', properties: { id: 3 }, geometry: { type: 'Point', coordinates: [20, 0] } }
]
}
data: points
}
}),
layers: Immutable.fromJS({
Expand All @@ -38,13 +32,13 @@ initialState = {
'circle-radius': 16,
'circle-color': '#f28a25'
},
filter: ['==', 'id', 0]
filter: ['==', 'id', '']
}
}),
viewport: {
latitude: 0,
longitude: 0,
zoom: 2
zoom: 0
}
};

Expand All @@ -62,7 +56,7 @@ const onClick = (event) => {

<MapGL
style={{ width: "100%", height: "400px" }}
mapStyle={state.mapStyle}
mapStyle="mapbox://styles/mapbox/light-v9"
accessToken={MAPBOX_ACCESS_TOKEN}
{...state.viewport}
>
Expand Down
26 changes: 10 additions & 16 deletions docs/hoverable-map.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
```jsx
const Immutable = require('immutable');
const random = require('@turf/random');

const points = random('points', 10);
points.features.forEach((feature, index) => {
feature.properties.id = index;
});

initialState = {
mapStyle: Immutable.fromJS({
version: 8,
sources: {},
layers: []
}),
sources: Immutable.fromJS({
markers: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{ type: 'Feature', properties: { id: 1 }, geometry: { type: 'Point', coordinates: [0, 20] } },
{ type: 'Feature', properties: { id: 2 }, geometry: { type: 'Point', coordinates: [-20, 0] } },
{ type: 'Feature', properties: { id: 3 }, geometry: { type: 'Point', coordinates: [20, 0] } }
]
}
data: points
}
}),
layers: Immutable.fromJS({
Expand All @@ -38,13 +32,13 @@ initialState = {
'circle-radius': 16,
'circle-color': '#f28a25'
},
filter: ['==', 'id', 0]
filter: ['==', 'id', '']
}
}),
viewport: {
latitude: 0,
longitude: 0,
zoom: 2
zoom: 0
}
};

Expand All @@ -62,7 +56,7 @@ const onHover = (event) => {

<MapGL
style={{ width: "100%", height: "400px" }}
mapStyle={state.mapStyle}
mapStyle="mapbox://styles/mapbox/light-v9"
accessToken={MAPBOX_ACCESS_TOKEN}
{...state.viewport}
>
Expand Down
2 changes: 1 addition & 1 deletion docs/immutable-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ initialState = {
}
};

const styleUrl = `https://api.mapbox.com/styles/v1/mapbox/streets-v9?access_token=${MAPBOX_ACCESS_TOKEN}`;
const styleUrl = `https://api.mapbox.com/styles/v1/mapbox/light-v9?access_token=${MAPBOX_ACCESS_TOKEN}`;

if (!state.mapStyle) {
fetch(styleUrl)
Expand Down
2 changes: 1 addition & 1 deletion docs/interactive-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ initialState = {

<MapGL
style={{ width: "100%", height: "400px" }}
mapStyle="mapbox://styles/mapbox/streets-v9"
mapStyle="mapbox://styles/mapbox/light-v9"
accessToken={MAPBOX_ACCESS_TOKEN}
onViewportChange={viewport => setState({ viewport })}
{...state.viewport}
Expand Down
2 changes: 1 addition & 1 deletion docs/static-map.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
```jsx
<MapGL
style={{ width: "100%", height: "400px" }}
mapStyle="mapbox://styles/mapbox/streets-v9"
mapStyle="mapbox://styles/mapbox/light-v9"
accessToken={MAPBOX_ACCESS_TOKEN}
latitude={37.78}
longitude={-122.41}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"mapbox-gl": "^0.40.0"
},
"devDependencies": {
"@turf/random": "4.7.3",
"babel-core": "6.26.0",
"babel-eslint": "8.0.1",
"babel-jest": "21.2.0",
Expand Down
54 changes: 54 additions & 0 deletions src/components/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ type Props = {
*/
onHover: (event: mapboxgl.MapEvent) => any,

/**
* Called when the layer feature is entered.
* @callback
* @param {Object} event - The mouse event.
* @param {[Number, Number]} event.lngLat - The coordinates of the pointer
* @param {Array} event.features - The features under the pointer, using Mapbox's
* queryRenderedFeatures API:
* https://www.mapbox.com/mapbox-gl-js/api/#Map#queryRenderedFeatures
*/
onEnter: (event: mapboxgl.MapEvent) => any,

/**
* Called when the layer feature is leaved.
* @callback
* @param {Object} event - The mouse event.
* @param {[Number, Number]} event.lngLat - The coordinates of the pointer
* @param {Array} event.features - The features under the pointer, using Mapbox's
* queryRenderedFeatures API:
* https://www.mapbox.com/mapbox-gl-js/api/#Map#queryRenderedFeatures
*/
onLeave: (event: mapboxgl.MapEvent) => any,

/** Radius to detect features around a clicked/hovered point (defaults to 0) */
radius: number
};
Expand All @@ -47,6 +69,8 @@ class Layer extends PureComponent<Props> {
_id: string;
_onClick: (event: mapboxgl.MapEvent) => void;
_onHover: (event: mapboxgl.MapEvent) => void;
_onEnter: (event: mapboxgl.MapEvent) => void;
_onLeave: (event: mapboxgl.MapEvent) => void;

static defaultProps = {
onClick: null,
Expand All @@ -59,6 +83,8 @@ class Layer extends PureComponent<Props> {

this._onClick = this._onClick.bind(this);
this._onHover = this._onHover.bind(this);
this._onEnter = this._onEnter.bind(this);
this._onLeave = this._onLeave.bind(this);
}

componentDidMount() {
Expand All @@ -67,6 +93,8 @@ class Layer extends PureComponent<Props> {

map.on('click', this._id, this._onClick);
map.on('mousemove', this._id, this._onHover);
map.on('mouseenter', this._id, this._onEnter);
map.on('mouseleave', this._id, this._onLeave);
}

componentWillReceiveProps(newProps: Props) {
Expand Down Expand Up @@ -135,6 +163,32 @@ class Layer extends PureComponent<Props> {
}
}

_onEnter(event: mapboxgl.MapEvent): void {
if (this.props.onEnter) {
const { map, radius } = this.props;
const position = [event.point.x, event.point.y];

/* eslint-disable no-param-reassign */
event.features = queryRenderedFeatures(map, this._id, position, radius);
/* eslint-enable no-param-reassign */

this.props.onEnter(event);
}
}

_onLeave(event: mapboxgl.MapEvent): void {
if (this.props.onLeave) {
const { map, radius } = this.props;
const position = [event.point.x, event.point.y];

/* eslint-disable no-param-reassign */
event.features = queryRenderedFeatures(map, this._id, position, radius);
/* eslint-enable no-param-reassign */

this.props.onLeave(event);
}
}

render() {
return null;
}
Expand Down
23 changes: 12 additions & 11 deletions src/components/MapGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import type { MapStyle, Viewport } from '../types';

type Props = {
/** container className */
className: String,
className?: String,

/** container style */
style: Object,
style?: Object,

/** The Mapbox style. A string url or a MapboxGL style Immutable.Map object. */
mapStyle: string | MapStyle,
Expand All @@ -21,10 +21,7 @@ type Props = {
children?: Node,

/** Mapbox API access token for mapbox-gl-js. Required when using Mapbox vector tiles/styles. */
accessToken: string,

/** Mapbox WebGL context creation option. Useful when you want to export the canvas as a PNG. */
preserveDrawingBuffer: boolean,
accessToken?: string,

/** The longitude of the center of the map. */
longitude: number,
Expand All @@ -36,20 +33,23 @@ type Props = {
zoom: number,

/** Specify the bearing of the viewport */
bearing: number,
bearing?: number,

/** Specify the pitch of the viewport */
pitch: number,
pitch?: number,

/** Mapbox WebGL context creation option. Useful when you want to export the canvas as a PNG. */
preserveDrawingBuffer?: boolean,

/**
* `onViewportChange` callback is fired when the user interacted with the
* map. The object passed to the callback contains viewport properties
* such as `longitude`, `latitude`, `zoom` etc.
*/
onViewportChange: (viewport: Viewport) => void,
onViewportChange?: (viewport: Viewport) => void,

/** The onLoad callback for the map */
onLoad: Function
onLoad?: Function
};

type State = {
Expand All @@ -66,9 +66,9 @@ class MapGL extends PureComponent<Props, State> {
style: null,
mapStyle: 'mapbox://styles/mapbox/light-v8',
accessToken: null,
preserveDrawingBuffer: false,
bearing: 0,
pitch: 0,
preserveDrawingBuffer: false,
onViewportChange: null,
onLoad: null
};
Expand Down Expand Up @@ -200,6 +200,7 @@ class MapGL extends PureComponent<Props, State> {
bearing
};

// $FlowFixMe
this.props.onViewportChange(viewport);
}

Expand Down
Loading

0 comments on commit 684cb05

Please sign in to comment.