Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make all features fully interactive #100

Merged
merged 7 commits into from
Nov 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,30 @@
In order to use GL Draw you must instantiate the draw class like so:

```js
var Draw = mapboxgl.Draw();
var Draw = mapboxgl.Draw({ options });
map.addControl(Draw);
```

Draw only works after the map has loaded so it is wise to perform any interactions in the `load` event callback of mapbox-gl:

```js
map.on('load', function() {
Draw.set({ ... });
console.log(Draw.getAll());
...
});
```

### Options

option | values | function
--- | --- | ---
drawing | boolean | The ability to draw and delete features - default: `true`
interactive | boolean | Keep all features permanently in edit mode - default: `false`
keybindings | boolean | Keyboard shortcuts for drawing - default: true
controls | Object | drawable shapes - default `{ marker: true, line: true, shape: true, square: true }`


`mapboxgl.Draw()` returns an instance of the `Draw` class which has the following public API methods for getting and setting data:

###`.set(Object: geojsonFeature) -> String`
Expand Down Expand Up @@ -115,7 +135,7 @@ This method removes all geometries in Draw and deletes the history.

Draw fires off a number of events on draw and edit actions.

###`draw.start`
###`drawing.start`

Fired when a drawing is started. Passes an object with the the feature type to the callback (`{ featureType: <String> }`). Note that these are gl-draw feature type, one of `point`, `line`, `polygon`, `square`.

Expand All @@ -127,7 +147,7 @@ map.on('draw.start', function(e) {
});
```

###`draw.end`
###`drawing.end`

Fired when a drawing is finished. Passes an object with the feature type and the geojson geometry to the callback.

Expand All @@ -139,26 +159,15 @@ map.on('draw.end', function(e) {
});
```

###`draw.feature.update`

Fired while drawing when a new vertex is added. Passes the geometry being drawn to the callback.

Example:

```
map.on('draw.feature.update', function(e) {
alert('new draw edit!', JSON.stringify(e.geojson));
});
```

###`edit.new`

Fired while editting when a new edit is made. Passes the new geometry to the callback.
Fired while editting when a new edit is made. Passes an object with the new geometry and its drawId to the callback.

Example:

```
map.on('edit.new', function(e) {
alert('new edit!', JSON.stringify(e.geojson));
alert('new edit on', e.id, '->', JSON.stringify(e.geojson));
});
```
```
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ var Draw = mapboxgl.Draw();

map.addControl(Draw)
```
See [API.md](https://github.com/mapbox/gl-draw/blob/master/API.md) for advanced usage.

### See [API.md](https://github.com/mapbox/gl-draw/blob/master/API.md) for advanced usage.

### Developing

Expand Down
7 changes: 5 additions & 2 deletions debug/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div id='map'></div>
<script src='https://mapbox.s3.amazonaws.com/mapbox-gl-js/master/mapbox-gl-dev.js'></script>
<script src='../dist/mapboxgl.draw.js'></script>
<script>
<script type='text/javascript'>
mapboxgl.accessToken = localStorage.accessToken;

var map = new mapboxgl.Map({
Expand All @@ -29,7 +29,10 @@
position: 'top-left'
}));

var Draw = mapboxgl.Draw();
var Draw = mapboxgl.Draw({
interactive: true,
drawing: false
});
map.addControl(Draw);
</script>
</body>
Expand Down
128 changes: 69 additions & 59 deletions src/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

import R from 'ramda';
import mapboxgl from 'mapbox-gl';
import EditStore from './edit_store';
import { DOM, createButton } from './util';

// GL Styles
import themeEdit from './theme/edit';
import themeStyle from './theme/style';
import themeDrawing from './theme/drawing';
import { DOM, createButton } from './util';

// Data store
// Data stores
import Store from './store';
import EditStore from './edit_store';

// Control handlers
import Line from './geometries/line';
Expand All @@ -23,9 +25,10 @@ export default class Draw extends mapboxgl.Control {
super();

this.options = {
drawing: true,
interactive: false,
position: 'top-left',
keybindings: true,
geoJSON: [],
controls: {
marker: true,
line: true,
Expand All @@ -34,7 +37,7 @@ export default class Draw extends mapboxgl.Control {
}
};

Object.assign(this, options);
Object.assign(this.options, options);

// event listeners
this.drag = this._drag.bind(this);
Expand All @@ -57,48 +60,50 @@ export default class Draw extends mapboxgl.Control {
this._store.setEditStore(this._editStore);
this._editStore.setDrawStore(this._store);

// Build out draw controls
if (controls.line) {
this.lineStringCtrl = createButton(this._container, {
className: controlClass + ' line',
title: `LineString tool ${this.options.keybindings && '(l)'}`,
fn: this._drawLine.bind(this),
id: 'lineDrawBtn'
}, this._controlClass);
}
if (this.options.drawing) {
// Build draw controls
if (controls.line) {
this.lineStringCtrl = createButton(this._container, {
className: controlClass + ' line',
title: `LineString tool ${this.options.keybindings && '(l)'}`,
fn: this._drawLine.bind(this),
id: 'lineDrawBtn'
}, this._controlClass);
}

if (controls.shape) {
this.polygonCtrl = createButton(this._container, {
className: `${controlClass} shape`,
title: `Polygon tool ${this.options.keybindings && '(p)'}`,
fn: this._drawPolygon.bind(this),
id: 'polygonDrawBtn'
}, this._constrolClass);
}
if (controls.shape) {
this.polygonCtrl = createButton(this._container, {
className: `${controlClass} shape`,
title: `Polygon tool ${this.options.keybindings && '(p)'}`,
fn: this._drawPolygon.bind(this),
id: 'polygonDrawBtn'
}, this._constrolClass);
}

if (controls.square) {
this.squareCtrl = createButton(this._container, {
className: `${controlClass} square`,
title: `Square tool ${this.options.keybindings && '(s)'}`,
fn: this._drawSquare.bind(this),
id: 'squareDrawBtn'
}, this._controlClass);
}
if (controls.square) {
this.squareCtrl = createButton(this._container, {
className: `${controlClass} square`,
title: `Square tool ${this.options.keybindings && '(s)'}`,
fn: this._drawSquare.bind(this),
id: 'squareDrawBtn'
}, this._controlClass);
}

if (controls.marker) {
this.markerCtrl = createButton(this._container, {
className: `${controlClass} marker`,
title: `Marker tool ${this.options.keybindings && '(m)'}`,
fn: this._drawPoint.bind(this),
id: 'pointDrawBtn'
}, this._controlClass);
}
if (controls.marker) {
this.markerCtrl = createButton(this._container, {
className: `${controlClass} marker`,
title: `Marker tool ${this.options.keybindings && '(m)'}`,
fn: this._drawPoint.bind(this),
id: 'pointDrawBtn'
}, this._controlClass);
}

if (this.options.keybindings) {
map.getContainer().addEventListener('keyup', this.onKeyUp);
}
if (this.options.keybindings) {
map.getContainer().addEventListener('keyup', this.onKeyUp);
}

map.getContainer().addEventListener('keydown', this.onKeyDown);
map.getContainer().addEventListener('keydown', this.onKeyDown);
}

this._map = map;

Expand Down Expand Up @@ -141,6 +146,7 @@ export default class Draw extends mapboxgl.Control {
}

_onKeyUp(e) {
if (!this.drawing) return;

// draw shortcuts
const LINESTRING_KEY = 76; // (l)
Expand Down Expand Up @@ -194,22 +200,25 @@ export default class Draw extends mapboxgl.Control {
this._map.featuresAt(e.point, {
radius: 10,
includeGeometry: true,
layer: [ 'gl-draw-polygon', 'gl-draw-line', 'gl-draw-point' ]
layer: [ 'gl-draw-polygon',
'gl-draw-line',
'gl-draw-point' ]
}, (err, features) => {
if (err) throw err;
if (features.length) { // clicked on a feature
if (this._drawing) return;
this._edit(features[0].properties.drawId);
} else { // clicked outside all features
this._finishEdit();
if (!this.options.interactive)
this._finishEdit();
}
});
}

_edit(drawId) {
this._map.getContainer().addEventListener('mousedown', this.initiateDrag, true);

if (!this._editStore.inProgress())
if (!this._editStore.inProgress() && this.options.drawing)
this.deleteBtn = createButton(this._container, {
className: 'mapboxgl-ctrl-draw-btn trash',
title: 'delete',
Expand Down Expand Up @@ -299,36 +308,38 @@ export default class Draw extends mapboxgl.Control {
}

_drawPolygon() {
this._finishEdit();
if (!this.options.interactive)
this._finishEdit();
var polygon = new Polygon(this._map);
polygon.startDraw();
this._drawing = true;
}

_drawLine() {
this._finishEdit();
if (!this.options.interactive)
this._finishEdit();
var line = new Line(this._map);
line.startDraw();
this._drawing = true;
}

_drawSquare() {
this._finishEdit();
if (!this.options.interactive)
this._finishEdit();
var square = new Square(this._map);
square.startDraw();
this._drawing = true;
}

_drawPoint() {
this._finishEdit();
if (!this.options.interactive)
this._finishEdit();
var point = new Point(this._map);
point.startDraw();
this._drawing = true;
}

_mapState() {
var controlClass = this._controlClass;

this._map.on('load', () => {

// in progress drawing style
Expand Down Expand Up @@ -358,22 +369,18 @@ export default class Draw extends mapboxgl.Control {
});
themeEdit.forEach(style => { this._map.addLayer(style); });

this._map.on('draw.end', e => {
this._store.set(e.geometry);
DOM.removeClass(document.querySelectorAll('.' + controlClass), 'active');
});

this._map.on('drawing.new.update', e => {
this._map.getSource('drawing').setData(e.geojson);
});

// clear the drawing layer after a drawing is done
this._map.on('drawing.end', () => {
this._map.on('drawing.end', e => {
this._map.getSource('drawing').setData({
type: 'FeatureCollection',
features: []
});
this._drawing = false;
this._edit(e.geometry.getDrawId());
[ this.lineStringCtrl,
this.polygonCtrl,
this.squareCtrl,
Expand All @@ -393,16 +400,18 @@ export default class Draw extends mapboxgl.Control {
this._map.on('mousemove', e => {
this._map.featuresAt(e.point, {
radius: 7,
layer: ['gl-edit-point', 'gl-edit-point-mid']
layer: [ 'gl-edit-point', 'gl-edit-point-mid' ],
includeGeometry: true
}, (err, features) => {
if (err) throw err;
if (!features.length)
return this._map.getContainer().classList.remove('mapboxgl-draw-move-activated');

var vertex = R.find(feat => feat.properties.meta === 'vertex')(features);
var midpoint = R.find(feat => feat.properties.meta === 'midpoint')(features);
var marker = R.find(feat => feat.geometry.type === 'Point')(features);

if (vertex || midpoint) {
if (vertex || midpoint || marker) {
this._map.getContainer().classList.add('mapboxgl-draw-move-activated');
this.hoveringOnVertex = true;
}
Expand Down Expand Up @@ -455,6 +464,7 @@ export default class Draw extends mapboxgl.Control {
return;
}
this._store.set(feature);
this._edit(feature.getDrawId());
}
return feature.drawId;
}
Expand Down
Loading