diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2018-06-01 16:13:10 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2018-06-05 12:11:55 +0200 |
| commit | ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087 (patch) | |
| tree | b1f7754eb50896ab3681e35fa4e08be642b940c9 /app/components/SvgMap.js | |
| parent | 5852c980980de53e00d76a0bdb4b41bf5c0f5b39 (diff) | |
| download | mullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.tar.xz mullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.zip | |
Add formatted source code
Diffstat (limited to 'app/components/SvgMap.js')
| -rw-r--r-- | app/components/SvgMap.js | 173 |
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); |
