This is the P2PU Archive. If you want the current site, go to www.p2pu.org!

Online Maps with OpenLayers

Adding Dimension: Lines, Shapes, Video, and Drawing

Nick Doiron's picture
Wed, 2011-02-23 07:49

Point
 
You've already learned to create points on the map, from the first part of "Clickable Icons in OpenLayers"  - http://p2pu.org/webcraft/online-maps-openlayers/document/clickable-icons-openlayers
 
The point is the basis for OpenLayers's lines and shapes (sometimes called polylines and polygons).  This lesson will explain creating and styling these objects, and also cover built-in tools for your users to draw points, lines, and shapes onto the map.
 
Line
 
 
The first section on that page, a constructor, explains that to create a LineString, you need to send it an array (list) of points.  There are multiple ways to do this:
 
  • An easy way to set up a point list
pointA = new OpenLayers.Geometry.Point( ... ).transform( ... )
pointB = new OpenLayers.Geometry.Point( ... ).transform( ... )
pointList = [ pointA, pointB ];
 
  • One way to add these quickly is to use an array of coordinates, then a loop to turn those coordinates into points
 
// the array is a list of something (in this case, a lists of [ longitude, latitude ] lists
var linePts = [
    [ 91.811628, 24.904771 ],
    [ 91.810856, 24.91096   ],
    [ 91.817636, 24.911855 ],
    [ 91.831133, 24.907477 ],
    [ 91.841497, 24.898679 ],
    [ 91.841025, 24.895312 ],
    [ 91.837935, 24.891225 ],
    [ 91.842356, 24.889006 ],
    [ 91.853814, 24.888626 ]
];
 
// a FOR loop operates on each item inside a list
for( i=0; i<=linePts.length-1; i=i+1 ) {
    // turn this coordinate array into a point
  linePts[i] = new OpenLayers.Geometry.Point( linePts[i][0], linePts[i][1]);
    // use projection transformation
  linePts[i] = linePts[i].transform( map.displayProjection, map.projection);
}
 
For my example, I wanted a section of a river to stand out on my map of Sylhet, Bangladesh.  I found longitude and latitude values, put them together, and made this map:
 
 
Shape
 
Lines simply aren't enough.  To highlight buildings, properties, districts and any other area, you advance to a shape.  OpenLayers officially calls these Polygons, but if it's been awhile since you were in geometry class, you probably think of them as shapes: http://dev.openlayers.org/releases/OpenLayers-2.10/doc/apidocs/files/OpenLayers/Geometry/Polygon-js.html
 
You'd think that constructing a Polygon would be about the same as a line... trace the outside and you're done, right?  Well, what would you do about donut shapes, or countries within countries?  So a Polygon is a list of LinearRings.  A LinearRing - http://dev.openlayers.org/releases/OpenLayers-2.10/doc/apidocs/files/OpenLayers/Geometry/LinearRing-js.html - is a list of points which form an outer or inner boundary of the shape.  They're as easy to make as LineStrings, but automatically OpenLayers will connect the first and last points of a LinearRing.
 
For my example, I was thinking about outlining a state or a country, but there are better, accurate ways to do that: http://openlayers.org/dev/examples/cql-format.html
 
I decided instead to outline some buildings in Boston, and play a related video when someone clicks on themhttp://jsfiddle.net/ndoiron/UAxun/90/
This is some useful code if you were looking to add YouTube to your maps ( or open video ).
 
Multi-Geometry
 
If you want multiple points, lines, or shapes to be part of the same object -- particularly useful to style several objects at once, or to make clicking easy with any one object -- you can use Multi- objects.  Just send it a list of objects: http://dev.openlayers.org/releases/OpenLayers-2.10/doc/apidocs/files/OpenLayers/Geometry/MultiPoint-js.html
 
 
Advanced Style
 
You don't want all of your lines and polygons to look the same... that's boring.  Have a diverse amount of style items that you can set on each polygon.
 
The most noticeable things you can control are border and fill color, as well as transparency.
 
Hope to see people using these attributes
-strokeLinecap
-strokeDashstyle
 
 
 
Drawing Control
 
You aren't the only one who wants to draw on your map.  Users want to add their own favorite places, trace hiking trails, and select search areas.  Fortunately, OpenLayers has these tools baked in.  Here's a working example where you can practice drawing.  Click to draw, double-click to stop: http://openlayers.org/dev/examples/draw-feature.html
 
 
//start by creating the layer where polygons will go
var polygonLayer = new OpenLayers.Layer.Vector("Drawn Shapes");
map.addLayer(polygonLayer);
 
// OpenLayers.Handler.Polygon is only a number, but it tells DrawFeature what to draw 
polygonControl = new OpenLayers.Control.DrawFeature( polygonLayer, OpenLayers.Handler.Polygon );
polygonControl.featureAdded=useDrawnPolygon;
map.addControl(polygonControl);
polygonControl.activate();
 
We connect featureAdded event to the useDrawnPolygon function.  Let's make that now, and have it turn the finished polygons red.
 
function useDrawnPolygon( feature ) {
        // turn the polygon red and opaque
        feature.geometry.style.fillColor="red";
        feature.geometry.style.fillOpacity=1;
        // get a list of points (in case you want to use this for other applications)
        featurePts=feature.geometry.getVertices();
}
 

Comments

I can't get a different color

intro vert's picture
intro vert
Sun, 2011-03-06 06:17

I can't get a different color for the drawn shape. I've changed "red" to "green" and hex values and still get the default color. Any have this working? Can I see an example please?

Can you post your jsFiddle?

Nick Doiron's picture
Nick Doiron
Sun, 2011-03-06 06:30

Can you post your jsFiddle? I haven't tested that one, so maybe we'll need to do something else.

You also need to finish drawing (double-click) in order for the shape to be passed to that function.

You're right; it should be

Nick Doiron's picture
Nick Doiron
Sun, 2011-03-06 16:37

You're right; it should be feature.geometry.style.fillColor

After you create polygonControl, you can also set its style to determine what color the polygon is while you're drawing:

polygonControl.handler.style = style_green;

Then, to determine the final color of the polygon, set the color of the layer that you're drawing to

polygonLayer.style = style_green

So what is the useDrawnPolygon function most useful for? I'll work on a sample, but it's really useful for storing the user's polygon on a database or sending it to a web service.