Merge pull request #5977 from tschaub/draw-box
Convenience function for drawing boxes
This commit is contained in:
@@ -5,11 +5,8 @@ shortdesc: Example of using the ol.interaction.Draw interaction.
|
||||
docs: >
|
||||
Example of using the Draw interaction. Select a geometry type from the
|
||||
dropdown above to start drawing. To finish drawing, click the last
|
||||
point. To activate freehand drawing for lines and polygons, hold the `Shift`
|
||||
key. Square drawing is achieved by using Circle mode with a `geometryFunction`
|
||||
that creates a 4-sided regular polygon instead of a circle. Box drawing uses a
|
||||
custom `geometryFunction` that takes start and end point of a line with 2
|
||||
points and creates a rectangular box.
|
||||
point. To activate freehand drawing for lines, polygons, and circles, hold
|
||||
the `Shift` key.
|
||||
tags: "draw, edit, freehand, vector"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
@@ -20,8 +17,6 @@ tags: "draw, edit, freehand, vector"
|
||||
<option value="LineString">LineString</option>
|
||||
<option value="Polygon">Polygon</option>
|
||||
<option value="Circle">Circle</option>
|
||||
<option value="Square">Square</option>
|
||||
<option value="Box">Box</option>
|
||||
<option value="None">None</option>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Draw');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Circle');
|
||||
goog.require('ol.style.Fill');
|
||||
goog.require('ol.style.Stroke');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
var raster = new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
@@ -18,22 +13,7 @@ var raster = new ol.layer.Tile({
|
||||
var source = new ol.source.Vector({wrapX: false});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
source: source,
|
||||
style: new ol.style.Style({
|
||||
fill: new ol.style.Fill({
|
||||
color: 'rgba(255, 255, 255, 0.2)'
|
||||
}),
|
||||
stroke: new ol.style.Stroke({
|
||||
color: '#ffcc33',
|
||||
width: 2
|
||||
}),
|
||||
image: new ol.style.Circle({
|
||||
radius: 7,
|
||||
fill: new ol.style.Fill({
|
||||
color: '#ffcc33'
|
||||
})
|
||||
})
|
||||
})
|
||||
source: source
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
@@ -51,30 +31,9 @@ var draw; // global so we can remove it later
|
||||
function addInteraction() {
|
||||
var value = typeSelect.value;
|
||||
if (value !== 'None') {
|
||||
var geometryFunction, maxPoints;
|
||||
if (value === 'Square') {
|
||||
value = 'Circle';
|
||||
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
|
||||
} else if (value === 'Box') {
|
||||
value = 'LineString';
|
||||
maxPoints = 2;
|
||||
geometryFunction = function(coordinates, geometry) {
|
||||
if (!geometry) {
|
||||
geometry = new ol.geom.Polygon(null);
|
||||
}
|
||||
var start = coordinates[0];
|
||||
var end = coordinates[1];
|
||||
geometry.setCoordinates([
|
||||
[start, [start[0], end[1]], end, [end[0], start[1]], start]
|
||||
]);
|
||||
return geometry;
|
||||
};
|
||||
}
|
||||
draw = new ol.interaction.Draw({
|
||||
source: source,
|
||||
type: /** @type {ol.geom.GeometryType} */ (value),
|
||||
geometryFunction: geometryFunction,
|
||||
maxPoints: maxPoints
|
||||
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
|
||||
});
|
||||
map.addInteraction(draw);
|
||||
}
|
||||
|
||||
22
examples/draw-freehand.html
Normal file
22
examples/draw-freehand.html
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Freehand Drawing
|
||||
shortdesc: Example using the ol.interaction.Draw interaction in freehand mode.
|
||||
docs: >
|
||||
This example demonstrates the `ol.interaction.Draw` in freehand mode. During
|
||||
freehand drawing, points are added while dragging. Set `freehand: true` to
|
||||
enable freehand mode. Note that freehand mode can be conditionally enabled
|
||||
by using the `freehandCondition` option. For example to toggle freehand mode
|
||||
with the `Shift` key, use `freehandCondition: ol.events.condition.shiftKeyOnly`.
|
||||
tags: "draw, edit, freehand, vector"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<form class="form-inline">
|
||||
<label>Geometry type </label>
|
||||
<select id="type">
|
||||
<option value="LineString">LineString</option>
|
||||
<option value="Polygon">Polygon</option>
|
||||
<option value="Circle">Circle</option>
|
||||
<option value="None">None</option>
|
||||
</select>
|
||||
</form>
|
||||
52
examples/draw-freehand.js
Normal file
52
examples/draw-freehand.js
Normal file
@@ -0,0 +1,52 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.interaction.Draw');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
|
||||
var raster = new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
});
|
||||
|
||||
var source = new ol.source.Vector({wrapX: false});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
source: source
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [raster, vector],
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: [-11000000, 4600000],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
|
||||
var typeSelect = document.getElementById('type');
|
||||
|
||||
var draw; // global so we can remove it later
|
||||
function addInteraction() {
|
||||
var value = typeSelect.value;
|
||||
if (value !== 'None') {
|
||||
draw = new ol.interaction.Draw({
|
||||
source: source,
|
||||
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value),
|
||||
freehand: true
|
||||
});
|
||||
map.addInteraction(draw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle change event.
|
||||
*/
|
||||
typeSelect.onchange = function() {
|
||||
map.removeInteraction(draw);
|
||||
addInteraction();
|
||||
};
|
||||
|
||||
addInteraction();
|
||||
25
examples/draw-shapes.html
Normal file
25
examples/draw-shapes.html
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Draw Shapes
|
||||
shortdesc: Using the ol.interaction.Draw to create regular shapes
|
||||
docs: >
|
||||
This demonstrates the use of the `geometryFunction` option for the
|
||||
`ol.interaction.Draw`. Select a shape type from the dropdown above to start
|
||||
drawing. To activate freehand drawing, hold the `Shift` key. Square drawing is
|
||||
achieved by using `type: 'Circle'` type with a `geometryFunction` that creates
|
||||
a 4-sided regular polygon instead of a circle. Box drawing uses `type: 'Circle'`
|
||||
with a `geometryFunction` that creates a box-shaped polygon instead of a
|
||||
circle. Star drawing uses a custom geometry function that coverts a circle
|
||||
into a start using the center and radius provided by the draw interaction.
|
||||
tags: "draw, edit, freehand, vector"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<form class="form-inline">
|
||||
<label>Shape type </label>
|
||||
<select id="type">
|
||||
<option value="Square">Square</option>
|
||||
<option value="Box">Box</option>
|
||||
<option value="Star">Star</option>
|
||||
<option value="None">None</option>
|
||||
</select>
|
||||
</form>
|
||||
86
examples/draw-shapes.js
Normal file
86
examples/draw-shapes.js
Normal file
@@ -0,0 +1,86 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Draw');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
|
||||
var raster = new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
});
|
||||
|
||||
var source = new ol.source.Vector({wrapX: false});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
source: source
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
layers: [raster, vector],
|
||||
target: 'map',
|
||||
view: new ol.View({
|
||||
center: [-11000000, 4600000],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
|
||||
var typeSelect = document.getElementById('type');
|
||||
|
||||
var draw; // global so we can remove it later
|
||||
function addInteraction() {
|
||||
var value = typeSelect.value;
|
||||
if (value !== 'None') {
|
||||
var geometryFunction;
|
||||
if (value === 'Square') {
|
||||
value = 'Circle';
|
||||
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
|
||||
} else if (value === 'Box') {
|
||||
value = 'Circle';
|
||||
geometryFunction = ol.interaction.Draw.createBox();
|
||||
} else if (value === 'Star') {
|
||||
value = 'Circle';
|
||||
geometryFunction = function(coordinates, geometry) {
|
||||
if (!geometry) {
|
||||
geometry = new ol.geom.Polygon(null);
|
||||
}
|
||||
var center = coordinates[0];
|
||||
var last = coordinates[1];
|
||||
var dx = center[0] - last[0];
|
||||
var dy = center[1] - last[1];
|
||||
var radius = Math.sqrt(dx * dx + dy * dy);
|
||||
var rotation = Math.atan2(dy, dx);
|
||||
var newCoordinates = [];
|
||||
var numPoints = 12;
|
||||
for (var i = 0; i < numPoints; ++i) {
|
||||
var angle = rotation + i * 2 * Math.PI / numPoints;
|
||||
var fraction = i % 2 === 0 ? 1 : 0.5;
|
||||
var offsetX = radius * fraction * Math.cos(angle);
|
||||
var offsetY = radius * fraction * Math.sin(angle);
|
||||
newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
|
||||
}
|
||||
newCoordinates.push(newCoordinates[0].slice());
|
||||
geometry.setCoordinates([newCoordinates]);
|
||||
return geometry;
|
||||
};
|
||||
}
|
||||
draw = new ol.interaction.Draw({
|
||||
source: source,
|
||||
type: /** @type {ol.geom.GeometryType} */ (value),
|
||||
geometryFunction: geometryFunction
|
||||
});
|
||||
map.addInteraction(draw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle change event.
|
||||
*/
|
||||
typeSelect.onchange = function() {
|
||||
map.removeInteraction(draw);
|
||||
addInteraction();
|
||||
};
|
||||
|
||||
addInteraction();
|
||||
@@ -2,6 +2,7 @@ goog.provide('ol.interaction.Draw');
|
||||
|
||||
goog.require('ol');
|
||||
goog.require('ol.events');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.events.Event');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
@@ -731,7 +732,7 @@ ol.interaction.Draw.prototype.updateState_ = function() {
|
||||
|
||||
|
||||
/**
|
||||
* Create a `geometryFunction` for `mode: 'Circle'` that will create a regular
|
||||
* Create a `geometryFunction` for `type: 'Circle'` that will create a regular
|
||||
* polygon with a user specified number of sides and start angle instead of an
|
||||
* `ol.geom.Circle` geometry.
|
||||
* @param {number=} opt_sides Number of sides of the regular polygon. Default is
|
||||
@@ -766,6 +767,36 @@ ol.interaction.Draw.createRegularPolygon = function(opt_sides, opt_angle) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a `geometryFunction` that will create a box-shaped polygon (aligned
|
||||
* with the coordinate system axes). Use this with the draw interaction and
|
||||
* `type: 'Circle'` to return a box instead of a circle geometry.
|
||||
* @return {ol.DrawGeometryFunctionType} Function that draws a box-shaped polygon.
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Draw.createBox = function() {
|
||||
return (
|
||||
/**
|
||||
* @param {ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>} coordinates
|
||||
* @param {ol.geom.SimpleGeometry=} opt_geometry
|
||||
* @return {ol.geom.SimpleGeometry}
|
||||
*/
|
||||
function(coordinates, opt_geometry) {
|
||||
var extent = ol.extent.boundingExtent(coordinates);
|
||||
var geometry = opt_geometry || new ol.geom.Polygon(null);
|
||||
geometry.setCoordinates([[
|
||||
ol.extent.getBottomLeft(extent),
|
||||
ol.extent.getBottomRight(extent),
|
||||
ol.extent.getTopRight(extent),
|
||||
ol.extent.getTopLeft(extent),
|
||||
ol.extent.getBottomLeft(extent)
|
||||
]]);
|
||||
return geometry;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the drawing mode. The mode for mult-part geometries is the same as for
|
||||
* their single-part cousins.
|
||||
|
||||
@@ -897,6 +897,35 @@ describe('ol.interaction.Draw', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ol.interaction.Draw.createBox', function() {
|
||||
it('creates a box-shaped polygon in Circle mode', function() {
|
||||
var draw = new ol.interaction.Draw({
|
||||
source: source,
|
||||
type: 'Circle',
|
||||
geometryFunction: ol.interaction.Draw.createBox()
|
||||
});
|
||||
map.addInteraction(draw);
|
||||
|
||||
// first point
|
||||
simulateEvent('pointermove', 0, 0);
|
||||
simulateEvent('pointerdown', 0, 0);
|
||||
simulateEvent('pointerup', 0, 0);
|
||||
|
||||
// finish on second point
|
||||
simulateEvent('pointermove', 20, 20);
|
||||
simulateEvent('pointerdown', 20, 20);
|
||||
simulateEvent('pointerup', 20, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
var geometry = features[0].getGeometry();
|
||||
expect(geometry).to.be.a(ol.geom.Polygon);
|
||||
var coordinates = geometry.getCoordinates();
|
||||
expect(coordinates[0]).to.have.length(5);
|
||||
expect(geometry.getArea()).to.equal(400);
|
||||
expect(geometry.getExtent()).to.eql([0, -20, 20, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extend an existing feature', function() {
|
||||
var draw;
|
||||
var feature;
|
||||
|
||||
Reference in New Issue
Block a user