import * as CommonSelectors from '../lib/common_selectors.js'; import doubleClickZoom from '../lib/double_click_zoom.js'; import * as Constants from '../constants.js'; import isEventAtCoordinates from '../lib/is_event_at_coordinates.js'; import createVertex from '../lib/create_vertex.js'; const DrawPolygon = {}; DrawPolygon.onSetup = function() { const polygon = this.newFeature({ type: Constants.geojsonTypes.FEATURE, properties: {}, geometry: { type: Constants.geojsonTypes.POLYGON, coordinates: [[]] } }); this.addFeature(polygon); this.clearSelectedFeatures(); doubleClickZoom.disable(this); this.updateUIClasses({ mouse: Constants.cursors.ADD }); this.activateUIButton(Constants.types.POLYGON); this.setActionableState({ trash: true }); return { polygon, currentVertexPosition: 0 }; }; DrawPolygon.clickAnywhere = function(state, e) { if (state.currentVertexPosition > 0 && isEventAtCoordinates(e, state.polygon.coordinates[0][state.currentVertexPosition - 1])) { return this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.polygon.id] }); } this.updateUIClasses({ mouse: Constants.cursors.ADD }); state.polygon.updateCoordinate(`0.${state.currentVertexPosition}`, e.lngLat.lng, e.lngLat.lat); state.currentVertexPosition++; state.polygon.updateCoordinate(`0.${state.currentVertexPosition}`, e.lngLat.lng, e.lngLat.lat); }; DrawPolygon.clickOnVertex = function(state) { return this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.polygon.id] }); }; DrawPolygon.onMouseMove = function(state, e) { state.polygon.updateCoordinate(`0.${state.currentVertexPosition}`, e.lngLat.lng, e.lngLat.lat); if (CommonSelectors.isVertex(e)) { this.updateUIClasses({ mouse: Constants.cursors.POINTER }); } }; DrawPolygon.onTap = DrawPolygon.onClick = function(state, e) { if (CommonSelectors.isVertex(e)) return this.clickOnVertex(state, e); return this.clickAnywhere(state, e); }; DrawPolygon.onKeyUp = function(state, e) { if (CommonSelectors.isEscapeKey(e)) { this.deleteFeature([state.polygon.id], { silent: true }); this.changeMode(Constants.modes.SIMPLE_SELECT); } else if (CommonSelectors.isEnterKey(e)) { this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.polygon.id] }); } }; DrawPolygon.onStop = function(state) { this.updateUIClasses({ mouse: Constants.cursors.NONE }); doubleClickZoom.enable(this); this.activateUIButton(); // check to see if we've deleted this feature if (this.getFeature(state.polygon.id) === undefined) return; //remove last added coordinate state.polygon.removeCoordinate(`0.${state.currentVertexPosition}`); if (state.polygon.isValid()) { this.fire(Constants.events.CREATE, { features: [state.polygon.toGeoJSON()] }); } else { this.deleteFeature([state.polygon.id], { silent: true }); this.changeMode(Constants.modes.SIMPLE_SELECT, {}, { silent: true }); } }; DrawPolygon.toDisplayFeatures = function(state, geojson, display) { const isActivePolygon = geojson.properties.id === state.polygon.id; geojson.properties.active = (isActivePolygon) ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE; if (!isActivePolygon) return display(geojson); // Don't render a polygon until it has two positions // (and a 3rd which is just the first repeated) if (geojson.geometry.coordinates.length === 0) return; const coordinateCount = geojson.geometry.coordinates[0].length; // 2 coordinates after selecting a draw type // 3 after creating the first point if (coordinateCount < 3) { return; } geojson.properties.meta = Constants.meta.FEATURE; display(createVertex(state.polygon.id, geojson.geometry.coordinates[0][0], '0.0', false)); if (coordinateCount > 3) { // Add a start position marker to the map, clicking on this will finish the feature // This should only be shown when we're in a valid spot const endPos = geojson.geometry.coordinates[0].length - 3; display(createVertex(state.polygon.id, geojson.geometry.coordinates[0][endPos], `0.${endPos}`, false)); } if (coordinateCount <= 4) { // If we've only drawn two positions (plus the closer), // make a LineString instead of a Polygon const lineCoordinates = [ [geojson.geometry.coordinates[0][0][0], geojson.geometry.coordinates[0][0][1]], [geojson.geometry.coordinates[0][1][0], geojson.geometry.coordinates[0][1][1]] ]; // create an initial vertex so that we can track the first point on mobile devices display({ type: Constants.geojsonTypes.FEATURE, properties: geojson.properties, geometry: { coordinates: lineCoordinates, type: Constants.geojsonTypes.LINE_STRING } }); if (coordinateCount === 3) { return; } } // render the Polygon return display(geojson); }; DrawPolygon.onTrash = function(state) { this.deleteFeature([state.polygon.id], { silent: true }); this.changeMode(Constants.modes.SIMPLE_SELECT); }; export default DrawPolygon;