summaryrefslogtreecommitdiffhomepage
path: root/app/components/SvgMap.js
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2018-06-01 16:13:10 +0200
committerAndrej Mihajlov <and@mullvad.net>2018-06-05 12:11:55 +0200
commitca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087 (patch)
treeb1f7754eb50896ab3681e35fa4e08be642b940c9 /app/components/SvgMap.js
parent5852c980980de53e00d76a0bdb4b41bf5c0f5b39 (diff)
downloadmullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.tar.xz
mullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.zip
Add formatted source code
Diffstat (limited to 'app/components/SvgMap.js')
-rw-r--r--app/components/SvgMap.js173
1 files changed, 94 insertions, 79 deletions
diff --git a/app/components/SvgMap.js b/app/components/SvgMap.js
index 48288f9a8a..43f1e2ef71 100644
--- a/app/components/SvgMap.js
+++ b/app/components/SvgMap.js
@@ -1,7 +1,14 @@
// @flow
import * as React from 'react';
-import { ComposableMap, ZoomableGroup, Geographies, Geography, Markers, Marker } from 'react-simple-maps';
+import {
+ ComposableMap,
+ ZoomableGroup,
+ Geographies,
+ Geography,
+ Markers,
+ Marker,
+} from 'react-simple-maps';
import { geoTimes } from 'd3-geo-projection';
import rbush from 'rbush';
@@ -56,7 +63,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
};
_projectionConfig = {
- scale: 160
+ scale: 160,
};
constructor(props: SvgMapProps) {
@@ -66,8 +73,8 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
}
componentWillReceiveProps(nextProps: SvgMapProps) {
- if(this._shouldInvalidateState(nextProps)) {
- this.setState(prevState => this._getNextState(prevState, nextProps));
+ if (this._shouldInvalidateState(nextProps)) {
+ this.setState((prevState) => this._getNextState(prevState, nextProps));
}
}
@@ -75,18 +82,13 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return (
this.props.width !== nextProps.width ||
this.props.height !== nextProps.height ||
-
this.props.center[0] !== nextProps.center[0] ||
this.props.center[1] !== nextProps.center[1] ||
-
this.props.offset[0] !== nextProps.offset[0] ||
this.props.offset[1] !== nextProps.offset[1] ||
-
this.props.zoomLevel !== nextProps.zoomLevel ||
-
this.props.showMarker !== nextProps.showMarker ||
this.props.markerImagePath !== nextProps.markerImagePath ||
-
this.state.zoomCenter !== nextState.zoomCenter ||
this.state.zoomLevel !== nextState.zoomLevel
);
@@ -100,7 +102,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
};
const zoomableGroupStyle = {
- transition: `transform ${MOVE_SPEED}ms ease-in-out`
+ transition: `transform ${MOVE_SPEED}ms ease-in-out`,
};
const geographyStyle = this._mergeRsmStyle({
@@ -108,7 +110,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
fill: '#294d73',
stroke: '#192e45',
strokeWidth: `${1 / this.state.zoomLevel}`,
- }
+ },
});
const stateProvinceLineStyle = this._mergeRsmStyle({
@@ -116,7 +118,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
fill: 'transparent',
stroke: '#192e45',
strokeWidth: `${1 / this.state.zoomLevel}`,
- }
+ },
});
const markerStyle = this._mergeRsmStyle({
@@ -128,71 +130,74 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
// disable CSS transition when moving between locations
// by using the different "key"
const userMarker = this.props.showMarker && (
- <Marker key={ `user-location-${ this.props.center.join('-') }` }
+ <Marker
+ key={`user-location-${this.props.center.join('-')}`}
marker={{ coordinates: this.props.center }}
- style={ markerStyle }>
- <image x="-30" y="-30" href={ this.props.markerImagePath } />
+ style={markerStyle}>
+ <image x="-30" y="-30" href={this.props.markerImagePath} />
</Marker>
);
- const countryMarkers = this.state.visibleCountries.map(item => (
- <Marker key={ `country-${item.id}` }
+ const countryMarkers = this.state.visibleCountries.map((item) => (
+ <Marker
+ key={`country-${item.id}`}
marker={{ coordinates: item.geometry.coordinates }}
- style={ markerStyle }>
+ style={markerStyle}>
<text fill="rgba(255,255,255,.6)" fontSize="22" textAnchor="middle">
- { item.properties.name }
+ {item.properties.name}
</text>
</Marker>
));
- const cityMarkers = this.state.visibleCities.map(item => (
- <Marker key={ `city-${item.id}` }
+ const cityMarkers = this.state.visibleCities.map((item) => (
+ <Marker
+ key={`city-${item.id}`}
marker={{ coordinates: item.geometry.coordinates }}
- style={ markerStyle }>
+ style={markerStyle}>
<circle r="2" fill="rgba(255,255,255,.6)" />
<text x="0" y="-10" fill="rgba(255,255,255,.6)" fontSize="16" textAnchor="middle">
- { item.properties.name }
+ {item.properties.name}
</text>
</Marker>
));
return (
<ComposableMap
- width={ this.props.width }
- height={ this.props.height }
- style={ mapStyle }
- projection={ this._getProjection }
- projectionConfig={ this._projectionConfig }>
+ width={this.props.width}
+ height={this.props.height}
+ style={mapStyle}
+ projection={this._getProjection}
+ projectionConfig={this._projectionConfig}>
<ZoomableGroup
- center={ this.state.zoomCenter }
- zoom={ this.state.zoomLevel }
- disablePanning={ false }
- style={ zoomableGroupStyle }>
- <Geographies geography={ geographyData } disableOptimization={ true }>
+ center={this.state.zoomCenter}
+ zoom={this.state.zoomLevel}
+ disablePanning={false}
+ style={zoomableGroupStyle}>
+ <Geographies geography={geographyData} disableOptimization={true}>
{(geographies, projection) => {
return this.state.visibleGeometry.map(({ id }) => (
<Geography
- key={ id }
- geography={ geographies[id] }
- projection={ projection }
- style={ geographyStyle } />
+ key={id}
+ geography={geographies[id]}
+ projection={projection}
+ style={geographyStyle}
+ />
));
}}
</Geographies>
- <Geographies geography={ statesProvincesLinesData } disableOptimization={ true }>
+ <Geographies geography={statesProvincesLinesData} disableOptimization={true}>
{(geographies, projection) => {
return this.state.visibleStatesProvincesLines.map(({ id }) => (
<Geography
- key={ id }
- geography={ geographies[id] }
- projection={ projection }
- style={ stateProvinceLineStyle } />
+ key={id}
+ geography={geographies[id]}
+ projection={projection}
+ style={stateProvinceLineStyle}
+ />
));
}}
</Geographies>
- <Markers>
- { [...countryMarkers, ...cityMarkers, userMarker] }
- </Markers>
+ <Markers>{[...countryMarkers, ...cityMarkers, userMarker]}</Markers>
</ZoomableGroup>
</ComposableMap>
);
@@ -203,17 +208,21 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return {
default: defaultStyle,
hover: style.hover || defaultStyle,
- pressed: style.pressed || defaultStyle
+ pressed: style.pressed || defaultStyle,
};
}
- _getProjection(width: number, height: number, config: {
- scale?: number,
- xOffset?: number,
- yOffset?: number,
- rotation?: [number, number, number],
- precision?: number,
- }) {
+ _getProjection(
+ width: number,
+ height: number,
+ config: {
+ scale?: number,
+ xOffset?: number,
+ yOffset?: number,
+ rotation?: [number, number, number],
+ precision?: number,
+ },
+ ) {
const scale = config.scale || 160;
const xOffset = config.xOffset || 0;
const yOffset = config.yOffset || 0;
@@ -222,7 +231,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return geoTimes()
.scale(scale)
- .translate([ xOffset + width / 2, yOffset + height / 2 ])
+ .translate([xOffset + width / 2, yOffset + height / 2])
.rotate(rotation)
.precision(precision);
}
@@ -231,24 +240,22 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
center: [number, number],
offset: [number, number],
projection: Function,
- zoom: number
+ zoom: number,
) {
const pos = projection(center);
- return projection.invert([
- pos[0] + offset[0] / zoom,
- pos[1] + offset[1] / zoom
- ]);
+ return projection.invert([pos[0] + offset[0] / zoom, pos[1] + offset[1] / zoom]);
}
_getViewportGeoBoundingBox(
centerCoordinate: [number, number],
- width: number, height: number,
+ width: number,
+ height: number,
projection: Function,
- zoom: number
+ zoom: number,
) {
const center = projection(centerCoordinate);
- const halfWidth = width * 0.5 / zoom;
- const halfHeight = height * 0.5 / zoom;
+ const halfWidth = (width * 0.5) / zoom;
+ const halfHeight = (height * 0.5) / zoom;
const northWest = projection.invert([center[0] - halfWidth, center[1] - halfHeight]);
const southEast = projection.invert([center[0] + halfWidth, center[1] + halfHeight]);
@@ -267,13 +274,10 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return (
oldProps.width !== nextProps.width ||
oldProps.height !== nextProps.height ||
-
oldProps.center[0] !== nextProps.center[0] ||
oldProps.center[1] !== nextProps.center[1] ||
-
oldProps.offset[0] !== nextProps.offset[0] ||
oldProps.offset[1] !== nextProps.offset[1] ||
-
oldProps.zoomLevel !== nextProps.zoomLevel
);
}
@@ -283,27 +287,38 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
const projection = this._getProjection(width, height, this._projectionConfig);
const zoomCenter = this._getZoomCenter(center, offset, projection, zoomLevel);
- const viewportBbox = this._getViewportGeoBoundingBox(zoomCenter, width, height, projection, zoomLevel);
+ const viewportBbox = this._getViewportGeoBoundingBox(
+ zoomCenter,
+ width,
+ height,
+ projection,
+ zoomLevel,
+ );
const viewportBboxMatch = {
- minX: viewportBbox[0], minY: viewportBbox[1],
- maxX: viewportBbox[2], maxY: viewportBbox[3],
- };
-
- // combine previous and current viewports to get the rough area of transition
- const combinedViewportBboxMatch = prevState ? {
- minX: Math.min(viewportBbox[0], prevState.viewportBbox[0]),
- minY: Math.min(viewportBbox[1], prevState.viewportBbox[1]),
- maxX: Math.max(viewportBbox[2], prevState.viewportBbox[2]),
- maxY: Math.max(viewportBbox[3], prevState.viewportBbox[3]),
- } : {
minX: viewportBbox[0],
minY: viewportBbox[1],
maxX: viewportBbox[2],
maxY: viewportBbox[3],
};
- const visibleCountries = zoomLevel < 5 || zoomLevel > 20 ? [] : countryTree.search(viewportBboxMatch);
+ // combine previous and current viewports to get the rough area of transition
+ const combinedViewportBboxMatch = prevState
+ ? {
+ minX: Math.min(viewportBbox[0], prevState.viewportBbox[0]),
+ minY: Math.min(viewportBbox[1], prevState.viewportBbox[1]),
+ maxX: Math.max(viewportBbox[2], prevState.viewportBbox[2]),
+ maxY: Math.max(viewportBbox[3], prevState.viewportBbox[3]),
+ }
+ : {
+ minX: viewportBbox[0],
+ minY: viewportBbox[1],
+ maxX: viewportBbox[2],
+ maxY: viewportBbox[3],
+ };
+
+ const visibleCountries =
+ zoomLevel < 5 || zoomLevel > 20 ? [] : countryTree.search(viewportBboxMatch);
const visibleCities = zoomLevel >= 40 ? cityTree.search(viewportBboxMatch) : [];
const visibleGeometry = geometryTree.search(combinedViewportBboxMatch);
const visibleStatesProvincesLines = provincesStatesLinesTree.search(combinedViewportBboxMatch);