From bbbfc2a4dd836e59aa652c06e14fd5e1c027e8ef Mon Sep 17 00:00:00 2001 From: Xiaoji Chen Date: Mon, 30 Dec 2019 10:28:57 -0800 Subject: [PATCH] Add ScaleControl (#966) --- docs/components/scale-control.md | 38 ++++++++++++++++ examples/controls/src/app.js | 16 +++++-- src/components/scale-control.js | 76 ++++++++++++++++++++++++++++++++ src/index.js | 1 + website/src/constants/pages.js | 6 ++- 5 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 docs/components/scale-control.md create mode 100644 src/components/scale-control.js diff --git a/docs/components/scale-control.md b/docs/components/scale-control.md new file mode 100644 index 00000000..24108d38 --- /dev/null +++ b/docs/components/scale-control.md @@ -0,0 +1,38 @@ +# Scale Control + +This is a React equivalent of Mapbox's [ScaleControl](https://docs.mapbox.com/mapbox-gl-js/api/#scalecontrol). + +```js +import {Component} from 'react'; +import ReactMapGL, {ScaleControl} from 'react-map-gl'; + +class Map extends Component { + render() { + const {viewport, updateViewport} = this.props; + return ( + +
+ +
+
+ ); + } +} +``` + +## Properties + +##### `maxWidth` {Number} + +The maximum length of the scale control in pixels. Default `100`. + +##### `unit` {String} + +Unit of the distance, one of `'imperial'`, `'metric'` or `'nautical'`. + +## Styling + +Like its Mapbox counterpart, this control relies on the mapbox-gl stylesheet to work properly. Make sure to add the stylesheet to your page. + +## Source +[scale-control.js](https://github.com/uber/react-map-gl/tree/5.1-release/src/components/scale-control.js) diff --git a/examples/controls/src/app.js b/examples/controls/src/app.js index 9dfa19fe..bf5b81b0 100644 --- a/examples/controls/src/app.js +++ b/examples/controls/src/app.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import {render} from 'react-dom'; -import MapGL, {Popup, NavigationControl, FullscreenControl} from 'react-map-gl'; +import MapGL, {Popup, NavigationControl, FullscreenControl, ScaleControl} from 'react-map-gl'; import ControlPanel from './control-panel'; import Pins from './pins'; @@ -24,6 +24,13 @@ const navStyle = { padding: '10px' }; +const scaleControlStyle = { + position: 'absolute', + bottom: 36, + left: 0, + padding: '10px' +}; + export default class App extends Component { constructor(props) { super(props); @@ -82,12 +89,15 @@ export default class App extends Component { {this._renderPopup()} -
+
-
+
+
+ +
diff --git a/src/components/scale-control.js b/src/components/scale-control.js new file mode 100644 index 00000000..be4c3ed5 --- /dev/null +++ b/src/components/scale-control.js @@ -0,0 +1,76 @@ +// @flow +// Copyright (c) 2015 Uber Technologies, Inc. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +import React from 'react'; +import PropTypes from 'prop-types'; +import BaseControl from './base-control'; +import mapboxgl from '../utils/mapboxgl'; + +import type {BaseControlProps} from './base-control'; + +const propTypes = Object.assign({}, BaseControl.propTypes, { + maxWidth: PropTypes.number, + unit: PropTypes.oneOf(['imperial', 'metric', 'nautical']) +}); + +const defaultProps = Object.assign({}, BaseControl.defaultProps, { + maxWidth: 100, + unit: 'metric' +}); + +export type ScaleControlProps = BaseControlProps & { + maxWidth: number, + unit: string +}; + +export default class ScaleControl extends BaseControl { + static propTypes = propTypes; + static defaultProps = defaultProps; + + componentDidMount() { + const mapboxScaleControl = new mapboxgl.ScaleControl(); + mapboxScaleControl._map = this._context.map; + mapboxScaleControl._container = this._containerRef.current; + this._mapboxScaleControl = mapboxScaleControl; + + this._update(); + } + + _control: any = null; + _mapboxScaleControl: any = null; + + _update() { + const mapboxScaleControl = this._mapboxScaleControl; + if (mapboxScaleControl) { + mapboxScaleControl.options = this.props; + mapboxScaleControl._onMove(); + } + } + + _render() { + this._control = this._control || ( +
+ ); + // Likely viewport has changed + this._update(); + + return this._control; + } +} diff --git a/src/index.js b/src/index.js index 2018f0ba..1e3050ea 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,7 @@ export {default as Popup} from './components/popup'; export {default as FullscreenControl} from './components/fullscreen-control'; export {default as GeolocateControl} from './components/geolocate-control'; export {default as NavigationControl} from './components/navigation-control'; +export {default as ScaleControl} from './components/scale-control'; // Overlays export {default as CanvasOverlay} from './overlays/canvas-overlay'; diff --git a/website/src/constants/pages.js b/website/src/constants/pages.js index 03553396..e93cf795 100644 --- a/website/src/constants/pages.js +++ b/website/src/constants/pages.js @@ -56,7 +56,7 @@ const docPages = { content: getDocUrl('README.md') }, { - name: 'What\'s New', + name: "What's New", content: getDocUrl('whats-new.md') }, { @@ -163,6 +163,10 @@ const docPages = { name: 'Popup', content: getDocUrl('components/popup.md') }, + { + name: 'ScaleControl', + content: getDocUrl('components/scale-control.md') + }, { name: 'Source', content: getDocUrl('components/source.md')