What additional shapes can you draw on the OpenLayers map?
Drawing your own shapes in OpenLayers is a nice option, which gives us an opportunity to customize the existing map. I mean not only the plain map set by the basic coding but also the map, which is already equipped with some important data. A good example here is the map generated by the QGIS2Web plugin, which usually includes our product prepared in QGIS. In this case, when we still need to add something more than the standard map content, the drawing feature kit can be very vital.
We can draw at least several types of shapes in the OpenLayers maps, which have been developed across the existing libraries. For the most up-to-date library (at the time when this post is produced) – 6.9.0 the users can draw the following shape types (Pic. 1):
– lines,
– points,
– polygons,
– boxes,
– rectangles,
– circles,
– ellipses,
– stars,
– arrows.
All the codes for the aforementioned shapes you can find by searching the attached links beneath this text.
Apart from this standard kit presented above, the user can modify the JavaScript code slightly and get some additional objects in order to expand its signatures gear. It’s a really straightforward thing and can be achieved by modifying the code for the “Star” shape, which looks initially like this:
var starInteraction = new ol.interaction.Draw({ source: vectorLayer.getSource(), type: 'Circle', geometryFunction: function (coordinates, geometry) { if (!geometry) { geometry = new ol.geom.Polygon([]); } 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; } });
where the most interesting lines have been highlighted in blue and red. The most profitable is the red code lines, where you can do the modification without disturbing the rotation features. Below I have listed the 15 new shapes, which we can implement easily in our drawing kit.
A. FLAT TRIANGLE
var numPoints = 3; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 50 === 0 ? 0 : 2; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
B. EQUILATERAL TRIANGLE
var numPoints = 6; 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]);
C. ISOSCELES TRIANGLE
var numPoints = 3; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 0 ? 0.5 : 2; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
other approaches:
var fraction = i % 2 === 1 ? 7 : 4; var fraction = i % 10 === 0 ? 3 : 2;
D. DIAMOND
var numPoints = 4; 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]);
E. PENTAGON
var numPoints = 5; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 1 ? 2 : 2; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
F. HEXAGON
var numPoints = 6; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 3 === 3 ? 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]);
other approaches:
var fraction = i % 0 === 0 ? 1 : 0.5;
G. OCTAGON
var numPoints = 8; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 1 === 0 ? 1 : 10; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
H. BOW
var numPoints = 8; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 4 === 0 ? 1 : 10; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
I. PACMAN
var numPoints = 24; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 50 === 0 ? 0 : 2; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
J. 12 ARM STAR
var numPoints = 24; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 0 ? 0.5 : 25; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
K. 3 ARM CROSS
var numPoints = 6; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 0 ? 1 : 7.5; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
Other approaches:
var fraction = i % 2 === 1 ? 0.5 : 10;
L. 4 ARM CROSS
var numPoints = 8; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 0 ? 1 : 10; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
M. 4 ARM CROSS THIN
var numPoints = 8; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 0 ? 0.5 : 25; var offsetX = radius * fraction * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
N. PARALLELOGRAM
var numPoints = 8; for (var i = 0; i < numPoints; ++i) { var angle = rotation + i * 2 * Math.PI / numPoints; var fraction = i % 2 === 1 ? 1 : 1.5; var offsetX = (radius*3) * (fraction) * Math.cos(angle); var offsetY = radius * fraction * Math.sin(angle); newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
O. SEMICIRCLE
var numPoints = 48; for (var i = 0.5; i * 2 < 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]); }
As a summary of my approaches, please see all the considered shapes below:
and treat them purely as a proposal. I guess you can still fiddle with the code presented, both for the “Star” shape as well as others, and provide your own geometry, which you need. This article is mostly for OpenLayers users, who are in an entry-level position with javascript coding and can tweak just some values. If you are savvier with this stuff, the geometry section will be something too big to adjust.
Mariusz Krukar
References:
- Farkas G., 2016, Mastering OpenLayers 3, Packt Publishing, Birmingham
- Langley J.P., Perez A.S., 2016, OpenLayers 3.x Cookbook – Second Edition, Packt Publishing, Birmingham, ISBN 9781785287756
Links:
- https://openlayers.org/en/latest/examples/draw-shapes.html
- https://openlayers.org/en/latest/examples/draw-and-modify-features.html
- https://openlayers.org/en/latest/examples/regularshape.html
- OpenLayers – drawing shapes – code example 1
- http://tsauerwein.github.io/ol3/animation-flights/examples/draw-features.html
- OpenLayers – drawing geometric figures – code example
- https://www.giserdqy.com/wp-content/guids/ol-v4.6.5/apidoc/ol.interaction.Draw.html
- OpenLayers API draw (Chinese)
- https://openlayers.org/en/latest/examples/layer-z-index.html
- https://dolmenweb.it/viewers/openlayer/examples/draw-shapes.html
- https://openlayers.org/en/latest/examples/line-arrows.html
- https://openlayers.org/workshop/en/vector/draw.html
- Drawing regular shapes with OpenLayers
Forums:
- https://gis.stackexchange.com/questions/263626/drawing-shapes-and-features-in-openlayers-4
- OpenLayers can you draw some special shapes?
- https://stackoverflow.com/questions/45849772/styling-openlayers-draw-interaction
- https://gis.stackexchange.com/questions/303646/customize-behaviour-of-ol-interaction-draw-createbox-geometryfunction
- ol.interaction.Draw – start point
- https://stackoverflow.com/questions/46709716/openlayers-4-changing-the-draw-order-of-selected-features
- Draw shape – star
- https://stackoverflow.com/questions/41606206/draw-arrow-without-using-any-image-in-openlayers3
- https://stackoverflow.com/questions/50917824/openlayer-4-draw-arrows-on-map/50922088
- https://stackoverflow.com/questions/31647238/how-to-draw-an-ellipse-using-openlayers3
- https://gis.stackexchange.com/questions/270603/drawing-ellipse-in-openlayers
- https://stackoverflow.com/questions/23264721/how-to-draw-circle-with-radius-in-openlayers
- https://stackoverflow.com/questions/33996409/draw-a-circle-with-defined-diameter-in-openlayers
My questions:
- https://stackoverflow.com/questions/69301542/openlayers-cant-draw-the-star
- https://stackoverflow.com/questions/69768050/problem-with-drawing-arrows-in-openlayers
- https://stackoverflow.com/questions/69311837/openlayers-circle-coordinates-are-missing