diff --git a/dist/Button/MeasureButton/MeasureButton.js b/dist/Button/MeasureButton/MeasureButton.js new file mode 100644 index 0000000000..feae5a0399 --- /dev/null +++ b/dist/Button/MeasureButton/MeasureButton.js @@ -0,0 +1,847 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _lodash = require('lodash'); + +var _map = require('ol/map'); + +var _map2 = _interopRequireDefault(_map); + +var _vector = require('ol/layer/vector'); + +var _vector2 = _interopRequireDefault(_vector); + +var _vector3 = require('ol/source/vector'); + +var _vector4 = _interopRequireDefault(_vector3); + +var _collection = require('ol/collection'); + +var _collection2 = _interopRequireDefault(_collection); + +var _style = require('ol/style/style'); + +var _style2 = _interopRequireDefault(_style); + +var _stroke = require('ol/style/stroke'); + +var _stroke2 = _interopRequireDefault(_stroke); + +var _fill = require('ol/style/fill'); + +var _fill2 = _interopRequireDefault(_fill); + +var _circle = require('ol/style/circle'); + +var _circle2 = _interopRequireDefault(_circle); + +var _draw = require('ol/interaction/draw'); + +var _draw2 = _interopRequireDefault(_draw); + +var _observable = require('ol/observable'); + +var _observable2 = _interopRequireDefault(_observable); + +var _overlay = require('ol/overlay'); + +var _overlay2 = _interopRequireDefault(_overlay); + +var _ToggleButton = require('../ToggleButton/ToggleButton.js'); + +var _ToggleButton2 = _interopRequireDefault(_ToggleButton); + +var _MeasureUtil = require('../../Util/MeasureUtil/MeasureUtil'); + +var _MeasureUtil2 = _interopRequireDefault(_MeasureUtil); + +var _MapUtil = require('../../Util/MapUtil/MapUtil'); + +var _MapUtil2 = _interopRequireDefault(_MapUtil); + +require('./MeasureButton.less'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +/** + * The MeasureButton. + * + * @class The MeasureButton + * @extends React.Component + */ +var MeasureButton = function (_React$Component) { + _inherits(MeasureButton, _React$Component); + + /** + * Creates the MeasureButton. + * + * @constructs MeasureButton + */ + + + /** + * The properties. + * @type {Object} + */ + + + /** + * An array of created divs we use for the tooltips. Used to eventually + * clean up everything we added. + * + * @type{Array} + * @private + */ + + + /** + * The measure tooltip element. + * + * @type {Element} + * @private + */ + + + /** + * Overlay to show the help messages. + * + * @type {olOverlay} + * @private + */ + + + /** + * Currently drawn feature. + * + * @type {OlFeature} + * @private + */ + function MeasureButton(props) { + _classCallCheck(this, MeasureButton); + + var _this = _possibleConstructorReturn(this, (MeasureButton.__proto__ || Object.getPrototypeOf(MeasureButton)).call(this, props)); + + _this.className = 'react-geo-measurebutton'; + _this._feature = null; + _this._measureTooltip = null; + _this._helpTooltip = null; + _this._helpTooltipElement = null; + _this._measureTooltipElement = null; + _this._createdTooltipOverlays = []; + _this._createdTooltipDivs = []; + _this._eventKeys = { + drawstart: null, + drawend: null, + pointermove: null, + click: null + }; + + _this.onToggle = function (pressed) { + _this.cleanup(); + + if (pressed) { + _this.state.drawInteraction.setActive(pressed); + _this._eventKeys.drawstart = _this.state.drawInteraction.on('drawstart', _this.drawStart, _this); + _this._eventKeys.drawend = _this.state.drawInteraction.on('drawend', _this.drawEnd, _this); + _this._eventKeys.pointermove = _this.props.map.on('pointermove', _this.pointerMoveHandler, _this); + } + }; + + _this.createMeasureLayer = function () { + var _this$props = _this.props, + measureLayerName = _this$props.measureLayerName, + fillColor = _this$props.fillColor, + strokeColor = _this$props.strokeColor, + map = _this$props.map; + + + var measureLayer = _MapUtil2.default.getLayerByName(map, measureLayerName); + + if (!measureLayer) { + measureLayer = new _vector2.default({ + name: measureLayerName, + source: new _vector4.default({ + features: new _collection2.default() + }), + style: new _style2.default({ + fill: new _fill2.default({ + color: fillColor + }), + stroke: new _stroke2.default({ + color: strokeColor, + width: 2 + }), + image: new _circle2.default({ + radius: 7, + fill: new _fill2.default({ + color: fillColor + }) + }) + }) + }); + map.addLayer(measureLayer); + } + _this.setState({ measureLayer: measureLayer }, function () { + _this.createDrawInteraction(); + }); + }; + + _this.createDrawInteraction = function () { + var _this$props2 = _this.props, + fillColor = _this$props2.fillColor, + strokeColor = _this$props2.strokeColor, + measureType = _this$props2.measureType, + pressed = _this$props2.pressed, + map = _this$props2.map; + + + var maxPoints = measureType === 'angle' ? 2 : undefined; + var drawType = measureType === 'polygon' ? 'MultiPolygon' : 'MultiLineString'; + + var drawInteraction = new _draw2.default({ + name: 'react-geo_drawaction', + source: _this.state.measureLayer.getSource(), + type: drawType, + maxPoints: maxPoints, + style: new _style2.default({ + fill: new _fill2.default({ + color: fillColor + }), + stroke: new _stroke2.default({ + color: strokeColor, + lineDash: [10, 10], + width: 2 + }), + image: new _circle2.default({ + radius: 5, + stroke: new _stroke2.default({ + color: strokeColor + }), + fill: new _fill2.default({ + color: fillColor + }) + }) + }), + freehandCondition: function freehandCondition() { + return false; + } + }); + + drawInteraction.setActive(pressed); + drawInteraction.on('change:active', _this.onDrawInteractionActiveChange, _this); + map.addInteraction(drawInteraction); + + _this.setState({ drawInteraction: drawInteraction }); + }; + + _this.onDrawInteractionActiveChange = function () { + if (_this.state.drawInteraction.getActive()) { + _this.createHelpTooltip(); + _this.createMeasureTooltip(); + } else { + _this.removeHelpTooltip(); + _this.removeMeasureTooltip(); + } + }; + + _this.drawStart = function (evt) { + var _this$props3 = _this.props, + showMeasureInfoOnClickedPoints = _this$props3.showMeasureInfoOnClickedPoints, + multipleDrawing = _this$props3.multipleDrawing, + measureType = _this$props3.measureType, + map = _this$props3.map; + + + var source = _this.state.measureLayer.getSource(); + _this._feature = evt.feature; + + if (showMeasureInfoOnClickedPoints && measureType === 'line') { + _this._eventKeys.click = map.on('click', _this.addMeasureStopTooltip, _this); + } + + if (!multipleDrawing && source.getFeatures().length > 0) { + _this.cleanupTooltips(); + _this.createMeasureTooltip(); + _this.createHelpTooltip(); + source.clear(); + } + }; + + _this.drawEnd = function () { + var _this$props4 = _this.props, + measureType = _this$props4.measureType, + showMeasureInfoOnClickedPoints = _this$props4.showMeasureInfoOnClickedPoints, + measureTooltipCssClasses = _this$props4.measureTooltipCssClasses; + + + if (_this._eventKeys.click) { + _observable2.default.unByKey(_this._eventKeys.click); + } + + // Fix doubled label for lastPoint of line + if (showMeasureInfoOnClickedPoints && measureType === 'line') { + _this.removeMeasureTooltip(); + } else { + _this._measureTooltipElement.className = measureTooltipCssClasses.tooltip + ' ' + measureTooltipCssClasses.tooltipStatic; + _this._measureTooltip.setOffset([0, -7]); + } + + // unset sketch + _this._feature = null; + + // fix doubled label for last point of line + if (showMeasureInfoOnClickedPoints && measureType === 'line') { + _this._measureTooltipElement = null; + _this.createMeasureTooltip(); + } + }; + + _this.addMeasureStopTooltip = function (evt) { + var _this$props5 = _this.props, + measureType = _this$props5.measureType, + decimalPlacesInTooltips = _this$props5.decimalPlacesInTooltips, + map = _this$props5.map, + measureTooltipCssClasses = _this$props5.measureTooltipCssClasses; + + + if (!(0, _lodash.isEmpty)(_this._feature)) { + var geom = _this._feature.getGeometry(); + var value = measureType === 'line' ? _MeasureUtil2.default.formatLength(geom, map, decimalPlacesInTooltips) : _MeasureUtil2.default.formatArea(geom, map, decimalPlacesInTooltips); + + if (parseInt(value, 10) > 0) { + var div = document.createElement('div'); + div.className = measureTooltipCssClasses.tooltip + ' ' + measureTooltipCssClasses.tooltipStatic; + div.innerHTML = value; + var tooltip = new _overlay2.default({ + element: div, + offset: [0, -15], + positioning: 'bottom-center' + }); + map.addOverlay(tooltip); + tooltip.setPosition(evt.coordinate); + + _this._createdTooltipDivs.push(div); + _this._createdTooltipOverlays.push(tooltip); + } + } + }; + + _this.createMeasureTooltip = function () { + var _this$props6 = _this.props, + map = _this$props6.map, + measureTooltipCssClasses = _this$props6.measureTooltipCssClasses; + + + if (_this._measureTooltipElement) { + return; + } + + _this._measureTooltipElement = document.createElement('div'); + _this._measureTooltipElement.className = measureTooltipCssClasses.tooltip + ' ' + measureTooltipCssClasses.tooltipDynamic; + _this._measureTooltip = new _overlay2.default({ + element: _this._measureTooltipElement, + offset: [0, -15], + positioning: 'bottom-center' + }); + map.addOverlay(_this._measureTooltip); + }; + + _this.createHelpTooltip = function () { + var _this$props7 = _this.props, + map = _this$props7.map, + measureTooltipCssClasses = _this$props7.measureTooltipCssClasses; + + + if (_this._helpTooltipElement) { + return; + } + + _this._helpTooltipElement = document.createElement('div'); + _this._helpTooltipElement.className = measureTooltipCssClasses.tooltip; + _this._helpTooltip = new _overlay2.default({ + element: _this._helpTooltipElement, + offset: [15, 0], + positioning: 'center-left' + }); + map.addOverlay(_this._helpTooltip); + }; + + _this.removeHelpTooltip = function () { + if (_this._helpTooltip) { + _this.props.map.removeOverlay(_this._helpTooltip); + } + _this._helpTooltipElement = null; + _this._helpTooltip = null; + }; + + _this.removeMeasureTooltip = function () { + if (_this._measureTooltip) { + _this.props.map.removeOverlay(_this._measureTooltip); + } + _this._measureTooltipElement = null; + _this._measureTooltip = null; + }; + + _this.cleanupTooltips = function () { + var map = _this.props.map; + + + _this._createdTooltipOverlays.forEach(function (tooltipOverlay) { + map.removeOverlay(tooltipOverlay); + }); + + _this._createdTooltipOverlays = []; + + _this._createdTooltipDivs.forEach(function (tooltipDiv) { + var parent = tooltipDiv && tooltipDiv.parentNode; + if (parent) { + parent.removeChild(tooltipDiv); + } + }); + _this._createdTooltipDivs = []; + }; + + _this.cleanup = function () { + _this.state.drawInteraction.setActive(false); + + Object.keys(_this._eventKeys).forEach(function (key) { + if (_this._eventKeys[key]) { + _observable2.default.unByKey(_this._eventKeys[key]); + } + }); + _this.cleanupTooltips(); + _this.state.measureLayer.getSource().clear(); + }; + + _this.pointerMoveHandler = function (evt) { + var _this$props8 = _this.props, + clickToDrawText = _this$props8.clickToDrawText, + continuePolygonMsg = _this$props8.continuePolygonMsg, + continueLineMsg = _this$props8.continueLineMsg, + continueAngleMsg = _this$props8.continueAngleMsg, + measureType = _this$props8.measureType, + decimalPlacesInTooltips = _this$props8.decimalPlacesInTooltips, + map = _this$props8.map; + + + if (evt.dragging) { + return; + } + + if (!_this._helpTooltipElement || !_this._measureTooltipElement) { + return; + } + + var helpMsg = clickToDrawText; + var helpTooltipCoord = evt.coordinate; + var measureTooltipCoord = evt.coordinate; + + if (_this._feature) { + var output = void 0; + var geom = _this._feature.getGeometry(); + measureTooltipCoord = geom.getLastCoordinate(); + if (measureType === 'polygon') { + output = _MeasureUtil2.default.formatArea(geom, map, decimalPlacesInTooltips); + helpMsg = continuePolygonMsg; + // attach area at interior point + measureTooltipCoord = geom.getInteriorPoint().getCoordinates(); + } else if (measureType === 'line') { + output = _MeasureUtil2.default.formatLength(geom, map, decimalPlacesInTooltips); + helpMsg = continueLineMsg; + measureTooltipCoord = geom.getLastCoordinate(); + } else if (measureType === 'angle') { + output = _MeasureUtil2.default.formatAngle(geom, map, decimalPlacesInTooltips); + helpMsg = continueAngleMsg; + } + _this._measureTooltipElement.innerHTML = output; + _this._measureTooltip.setPosition(measureTooltipCoord); + } + + _this._helpTooltipElement.innerHTML = helpMsg; + _this._helpTooltip.setPosition(helpTooltipCoord); + }; + + _this.state = { + measureLayer: null, + drawInteraction: null + }; + return _this; + } + + /** + * `componentWillMount` method of the MeasureButton. Just calls a + * `createMeasureLayer` method. + * + * @method + */ + + + /** + * The default properties. + * @type {Object} + */ + + + /** + * An object holding keyed `OlEventsKey` instances returned by the `on` + * method of `OlObservable`. These keys are used to unbind temporary + * listeners on events of the `OlInteractionDraw` or `OlMap`. The keys + * are the names of the events on the various objects. The `click` key is + * not always bound, but only for certain #measureType values. + * + * In #cleanup, we unbind all events we have bound so as to not leak + * memory, and to ensure we have no concurring listeners being active at a + * time (E.g. when multiple measure buttons are in an application). + * + * @type {Object} + * @private + */ + + + /** + * An array of created overlays we use for the tooltips. Used to eventually + * clean up everything we added. + * + * @type{Array} + * @private + */ + + + /** + * The help tooltip element. + * + * @type {Element} + * @private + */ + + + /** + * Overlay to show the measurement. + * + * @type {olOverlay} + * @private + */ + + + /** + * The className added to this component. + * + * @type {String} + * @private + */ + + + _createClass(MeasureButton, [{ + key: 'componentWillMount', + value: function componentWillMount() { + this.createMeasureLayer(); + } + + /** + * Called when the button is toggled, this method ensures that everything + * is cleaned up when unpressed, and that measuring can start when pressed. + * + * @method + */ + + + /** + * Creates measure vector layer and add this to the map. + * + * @method + */ + + + /** + * Creates a correctly configured OL draw interaction depending on + * the configured measureType. + * + * @return {OlInteractionDraw} The created interaction, which is not yet + * added to the map. + * + * @method + */ + + + /** + * Adjusts visibility of measurement related tooltips depending on active + * status of draw interaction. + * + * @method + */ + + + /** + * Sets up listeners whenever the drawing of a measurement sketch is + * started. + * + * @param {OlInteractionDrawEvent} evt The event which contains the + * feature we are drawing. + * + * @method + */ + + + /** + * Called whenever measuring stops, this method draws static tooltips with + * the result onto the map canvas and unregisters various listeners. + * + * @method + */ + + + /** + * Adds a tooltip on click where a measuring stop occured. + * + * @param {OlMapBrowserEvent} evt The event which contains the coordinate + * for the tooltip. + * + * @method + */ + + + /** + * Creates a new measure tooltip as `OlOverlay`. + * + * @method + */ + + + /** + * Creates a new help tooltip as `OlOverlay`. + * + * @method + */ + + + /** + * Removes help tooltip from the map if measure button was untoggled. + * + * @method + */ + + + /** + * Removes measure tooltip from the map if measure button was untoggled. + * + * @method + */ + + + /** + * Cleans up tooltips when the button is unpressed. + * + * @method + */ + + + /** + * Cleans up artifacts from measuring when the button is unpressed. + * + * @method + */ + + + /** + * Handle pointer move by updating and repositioning the dynamic tooltip. + * + * @param {OlMapBrowserEvent} evt The event from the pointermove. + * + * @method + */ + + }, { + key: 'render', + + + /** + * The render function. + */ + value: function render() { + var _props = this.props, + className = _props.className, + map = _props.map, + measureType = _props.measureType, + measureLayerName = _props.measureLayerName, + fillColor = _props.fillColor, + strokeColor = _props.strokeColor, + showMeasureInfoOnClickedPoints = _props.showMeasureInfoOnClickedPoints, + multipleDrawing = _props.multipleDrawing, + clickToDrawText = _props.clickToDrawText, + continuePolygonMsg = _props.continuePolygonMsg, + continueLineMsg = _props.continueLineMsg, + continueAngleMsg = _props.continueAngleMsg, + decimalPlacesInTooltips = _props.decimalPlacesInTooltips, + measureTooltipCssClasses = _props.measureTooltipCssClasses, + passThroughProps = _objectWithoutProperties(_props, ['className', 'map', 'measureType', 'measureLayerName', 'fillColor', 'strokeColor', 'showMeasureInfoOnClickedPoints', 'multipleDrawing', 'clickToDrawText', 'continuePolygonMsg', 'continueLineMsg', 'continueAngleMsg', 'decimalPlacesInTooltips', 'measureTooltipCssClasses']); + + var finalClassName = className ? className + ' ' + this.className : this.className; + + return _react2.default.createElement(_ToggleButton2.default, _extends({ + onToggle: this.onToggle, + className: finalClassName + }, passThroughProps)); + } + }]); + + return MeasureButton; +}(_react2.default.Component); + +MeasureButton.propTypes = { + /** + * The className which should be added. + * + * @type {String} + */ + className: _propTypes2.default.string, + + /** + * Instance of OL map this component is bound to. + * + * @type {OlMap} + */ + map: _propTypes2.default.instanceOf(_map2.default).isRequired, + + /** + * Whether line, area or angle will be measured. + * + * @type {String} + */ + measureType: _propTypes2.default.oneOf(['line', 'polygon', 'angle']).isRequired, + + /** + * Name of system vector layer which will be used to draw measurement + * results. + * + * @type {String} + */ + measureLayerName: _propTypes2.default.string, + + /** + * Fill color of the measurement feature. + * + * @type {String} + */ + fillColor: _propTypes2.default.string, + + /** + * Stroke color of the measurement feature. + * + * @type {String} + */ + strokeColor: _propTypes2.default.string, + + /** + * Determines if a marker with current measurement should be shown every + * time the user clicks while drawing. Default is false. + * + * @type {Boolean} + */ + showMeasureInfoOnClickedPoints: _propTypes2.default.bool, + + /** + * Used to allow / disallow multiple drawings at a time on the map. + * Default is false. + * TODO known issue: only label of the last drawn feature will be shown! + * + * @type {Boolean} + */ + multipleDrawing: _propTypes2.default.bool, + + /** + * Tooltip which will be shown on map mouserover after measurement button + * was activated. + * + * @type {String} + */ + clickToDrawText: _propTypes2.default.string, + + /** + * Tooltip which will be shown after polygon measurement button was toggled + * and at least one click in the map is occured. + * + * @type {String} + */ + continuePolygonMsg: _propTypes2.default.string, + + /** + * Tooltip which will be shown after line measurement button was toggled + * and at least one click in the map is occured. + * + * @type {String} + */ + continueLineMsg: _propTypes2.default.string, + + /** + * Tooltip which will be shown after angle measurement button was toggled + * and at least one click in the map is occured. + * + * @type {String} + */ + continueAngleMsg: _propTypes2.default.string, + + /** + * How many decimal places will be allowed for the measure tooltips. + * Default is 2. + * + * @param {Number} decimalPlacesInTooltips. + */ + decimalPlacesInTooltips: _propTypes2.default.number, + + /** + * CSS classes we'll assign to the popups and tooltips from measuring. + * Overwrite this object to style the text of the popups / overlays, if you + * don't want to use default classes. + * + * @param {Object} measureTooltipCssClasses + */ + measureTooltipCssClasses: _propTypes2.default.object, + + /** + * Whether the measure button is pressed. + * + * @param {Boolean} pressed + */ + pressed: _propTypes2.default.bool +}; +MeasureButton.defaultProps = { + measureLayerName: 'react-geo_measure', + fillColor: 'rgba(255, 0, 0, 0.5)', + strokeColor: 'rgba(255, 0, 0, 0.8)', + showMeasureInfoOnClickedPoints: false, + decimalPlacesInTooltips: 2, + multipleDrawing: false, + continuePolygonMsg: 'Click to draw area', + continueLineMsg: 'Click to draw line', + continueAngleMsg: 'Click to draw angle', + clickToDrawText: 'Click to measure', + measureTooltipCssClasses: { + tooltip: 'react-geo-measure-tooltip', + tooltipDynamic: 'react-geo-measure-tooltip-dynamic', + tooltipStatic: 'react-geo-measure-tooltip-static' + }, + pressed: false }; +exports.default = MeasureButton; \ No newline at end of file diff --git a/dist/Button/MeasureButton/MeasureButton.less b/dist/Button/MeasureButton/MeasureButton.less new file mode 100644 index 0000000000..f417381b9e --- /dev/null +++ b/dist/Button/MeasureButton/MeasureButton.less @@ -0,0 +1,60 @@ +@import '../../style/variables.less'; + +button.react-geo-measurebutton { + color: #fff; + background-color: @primary-color; + border-color: darken(@component-background, 10); + + &:focus{ + background-color: lighten(@primary-color, 10); + border-color: lighten(@component-background, 10); + } + + &:hover { + background-color: lighten(@primary-color, 10); + border-color: lighten(@component-background, 10); + } + + &:disabled { + background-color: @component-background; + border-color: darken(@component-background, 10); + } + + &.btn-pressed { + background-color: darken(@primary-color, 20); + border-color: darken(@component-background, 10); + } +} + +.react-geo-measure-tooltip { + position: relative; + background: @measure-dynamic-tooltip-background-color; + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.react-geo-measure-tooltip-dynamic { + opacity: 1; + font-weight: bold; +} +.react-geo-measure-tooltip-static { + background-color: @measure-static-tooltip-background-color; + color: black; + border: 1px solid white; +} +.react-geo-measure-tooltip-dynamic:before, +.react-geo-measure-tooltip-static:before { + border-top: 6px solid @measure-dynamic-tooltip-background-color; + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.react-geo-measure-tooltip-static:before { + border-top-color: @measure-static-tooltip-background-color; +} diff --git a/dist/Button/ToggleButton/ToggleButton.js b/dist/Button/ToggleButton/ToggleButton.js index 081ef106c1..1e1319b023 100644 --- a/dist/Button/ToggleButton/ToggleButton.js +++ b/dist/Button/ToggleButton/ToggleButton.js @@ -198,7 +198,8 @@ var ToggleButton = function (_React$Component) { _react2.default.createElement(_reactFa.Icon, { name: iconName, className: fontIcon - }) + }), + antBtnProps.children ) ); } diff --git a/dist/Util/MeasureUtil/MeasureUtil.js b/dist/Util/MeasureUtil/MeasureUtil.js new file mode 100644 index 0000000000..c820c44ff2 --- /dev/null +++ b/dist/Util/MeasureUtil/MeasureUtil.js @@ -0,0 +1,135 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _sphere = require('ol/sphere'); + +var _sphere2 = _interopRequireDefault(_sphere); + +var _proj = require('ol/proj'); + +var _proj2 = _interopRequireDefault(_proj); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * This class provides some static methods which might be helpful when working + * with measurements. + * + * @class MeasureUtil + */ +var MeasureUtil = function MeasureUtil() { + _classCallCheck(this, MeasureUtil); +}; + +MeasureUtil.formatLength = function (line, map, decimalPlacesInToolTips) { + var geodesic = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + + var decimalHelper = Math.pow(10, decimalPlacesInToolTips); + var length = void 0; + + if (geodesic) { + var wgs84Sphere = new _sphere2.default(6378137); + var coordinates = line.getCoordinates(); + length = 0; + var sourceProj = map.getView().getProjection(); + for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) { + var c1 = _proj2.default.transform(coordinates[i], sourceProj, 'EPSG:4326'); + var c2 = _proj2.default.transform(coordinates[i + 1], sourceProj, 'EPSG:4326'); + length += wgs84Sphere.haversineDistance(c1, c2); + } + } else { + length = Math.round(line.getLength() * 100) / 100; + } + + var output = void 0; + if (length > 1000) { + output = Math.round(length / 1000 * decimalHelper) / decimalHelper + ' ' + 'km'; + } else { + output = Math.round(length * decimalHelper) / decimalHelper + ' m'; + } + return output; +}; + +MeasureUtil.formatArea = function (polygon, map, decimalPlacesInToolTips) { + var geodesic = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + + var decimalHelper = Math.pow(10, decimalPlacesInToolTips); + var area = void 0; + + if (geodesic) { + var wgs84Sphere = new _sphere2.default(6378137); + var sourceProj = map.getView().getProjection(); + var geom = polygon.clone().transform(sourceProj, 'EPSG:4326'); + var coordinates = geom.getLinearRing(0).getCoordinates(); + area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); + } else { + area = polygon.getArea(); + } + + var output = void 0; + if (area > 10000) { + output = Math.round(area / 1000000 * decimalHelper) / decimalHelper + ' km2'; + } else { + output = Math.round(area * decimalHelper) / decimalHelper + ' ' + 'm2'; + } + return output; +}; + +MeasureUtil.angle = function (start, end) { + var dx = start[0] - end[0]; + var dy = start[1] - end[1]; + // range (-PI, PI] + var theta = Math.atan2(dy, dx); + // rads to degs, range (-180, 180] + theta *= 180 / Math.PI; + return theta; +}; + +MeasureUtil.angle360 = function (start, end) { + // range (-180, 180] + var theta = MeasureUtil.angle(start, end); + if (theta < 0) { + // range [0, 360) + theta = 360 + theta; + } + return theta; +}; + +MeasureUtil.makeClockwise = function (angle360) { + return 360 - angle360; +}; + +MeasureUtil.makeZeroDegreesAtNorth = function (angle360) { + var corrected = angle360 + 90; + if (corrected > 360) { + corrected = corrected - 360; + } + return corrected; +}; + +MeasureUtil.formatAngle = function (line) { + var decimalPlacesInToolTips = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; + + var coords = line.getCoordinates(); + var numCoords = coords.length; + if (numCoords < 2) { + return ''; + } + + var lastPoint = coords[numCoords - 1]; + var prevPoint = coords[numCoords - 2]; + var angle = MeasureUtil.angle360(prevPoint, lastPoint); + + angle = MeasureUtil.makeZeroDegreesAtNorth(angle); + angle = MeasureUtil.makeClockwise(angle); + angle = angle.toFixed(decimalPlacesInToolTips); + + return angle + '°'; +}; + +exports.default = MeasureUtil; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 4f60b76302..5f305dae69 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.isVisibleComponent = exports.mappify = exports.MapComponent = exports.MapProvider = exports.UrlUtil = exports.UndoUtil = exports.StringUtil = exports.ProjectionUtil = exports.ObjectUtil = exports.NominatimSearch = exports.CoordinateReferenceSystemCombo = exports.MapUtil = exports.Logger = exports.FeatureUtil = exports.CsrfUtil = exports.UserChip = exports.Toolbar = exports.Titlebar = exports.LayerTransparencySlider = exports.Panel = exports.ScaleCombo = exports.FloatingMapLogo = exports.Legend = exports.LayerTreeNode = exports.LayerTree = exports.FeatureGrid = exports.ToggleGroup = exports.ToggleButton = exports.SimpleButton = exports.CircleMenu = undefined; +exports.isVisibleComponent = exports.mappify = exports.MapComponent = exports.MapProvider = exports.UrlUtil = exports.UndoUtil = exports.StringUtil = exports.ProjectionUtil = exports.ObjectUtil = exports.NominatimSearch = exports.CoordinateReferenceSystemCombo = exports.MeasureUtil = exports.MapUtil = exports.Logger = exports.FeatureUtil = exports.CsrfUtil = exports.UserChip = exports.Toolbar = exports.Titlebar = exports.LayerTransparencySlider = exports.Panel = exports.ScaleCombo = exports.FloatingMapLogo = exports.Legend = exports.LayerTreeNode = exports.LayerTree = exports.FeatureGrid = exports.MeasureButton = exports.ToggleGroup = exports.ToggleButton = exports.SimpleButton = exports.CircleMenu = undefined; var _SimpleButton = require('./Button/SimpleButton/SimpleButton.js'); @@ -17,6 +17,10 @@ var _ToggleGroup = require('./Button/ToggleGroup/ToggleGroup.js'); var _ToggleGroup2 = _interopRequireDefault(_ToggleGroup); +var _MeasureButton = require('./Button/MeasureButton/MeasureButton.js'); + +var _MeasureButton2 = _interopRequireDefault(_MeasureButton); + var _CoordinateReferenceSystemCombo = require('./Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.js'); var _CoordinateReferenceSystemCombo2 = _interopRequireDefault(_CoordinateReferenceSystemCombo); @@ -89,6 +93,10 @@ var _MapUtil = require('./Util/MapUtil/MapUtil'); var _MapUtil2 = _interopRequireDefault(_MapUtil); +var _MeasureUtil = require('./Util/MeasureUtil/MeasureUtil'); + +var _MeasureUtil2 = _interopRequireDefault(_MeasureUtil); + var _ObjectUtil = require('./Util/ObjectUtil/ObjectUtil'); var _ObjectUtil2 = _interopRequireDefault(_ObjectUtil); @@ -127,6 +135,7 @@ exports.CircleMenu = _CircleMenu2.default; exports.SimpleButton = _SimpleButton2.default; exports.ToggleButton = _ToggleButton2.default; exports.ToggleGroup = _ToggleGroup2.default; +exports.MeasureButton = _MeasureButton2.default; exports.FeatureGrid = _FeatureGrid2.default; exports.LayerTree = _LayerTree2.default; exports.LayerTreeNode = _LayerTreeNode2.default; @@ -142,6 +151,7 @@ exports.CsrfUtil = _CsrfUtil2.default; exports.FeatureUtil = _FeatureUtil2.default; exports.Logger = _Logger2.default; exports.MapUtil = _MapUtil2.default; +exports.MeasureUtil = _MeasureUtil2.default; exports.CoordinateReferenceSystemCombo = _CoordinateReferenceSystemCombo2.default; exports.NominatimSearch = _NominatimSearch2.default; exports.ObjectUtil = _ObjectUtil2.default; diff --git a/dist/style/variables.less b/dist/style/variables.less index 0f11c4fa5d..9c49db87c6 100644 --- a/dist/style/variables.less +++ b/dist/style/variables.less @@ -1,6 +1,8 @@ -@primary-color: #9A1A38; -@link-color: #1DA57A; +@primary-color: rgb(154, 26, 56); +@link-color: rgb(29, 165, 122); @border-radius-base: 2px; -@layout-header-background: #E9E9E9; -@component-background: #E9E9E9; -@circle-menu-background-color: rgba(200, 199, 58, 0.65); \ No newline at end of file +@layout-header-background: rgb(233, 233, 233); +@component-background: rgb(233, 233, 233); +@circle-menu-background-color: rgba(200, 199, 58, 0.65); +@measure-static-tooltip-background-color: rgb(255, 204, 51); +@measure-dynamic-tooltip-background-color: rgba(0, 0, 0, 0.5);