Adding style to your OpenLayers

OpenLayers supports a subset of the SLD standard for stylesheets. Anything in an OpenLayers StyleMap can also be put into an SLD and parsed by the OpenLayers SLD parser. SLDs are limited in that they cannot perform smooth gradients, cannot combine multiple properties into a single output (you can get around this by imputing properties), as well as other limitations, but for many rendering tasks they can be quite useful.

The SLD is generally stored as a separate XML file on the server, then loaded asynchronously, applying the styles to layers as they are added to the map:

OpenLayers.loadURL("tasmania/sld-tasmania.xml", null, null, complete);

function getDefaultStyle(sld, layerName) {
	var styles = sld.namedLayers[layerName].userStyles;
	var style;
	for(var i=0; i

OpenLayers.loadURL is a proxy for the asynchronous XmlHTTPRequest method, just like in WFS, and this means that they must reside on the same server as the one serving the page, or they must be accessible via proxy. It also means that you cannot directly apply an SLD, but must instead wait to load layers until the SLD is completely loaded. Generally this is achieved with a callback method to the loadURL call – in this case, complete.

The getDefaultStyle function is a convenience function that traverses through a style document and finds a named style which can be associated with a layer.

Data driven feature styling

When the SLD standard fails to encompass your styling needs, and it often will, you’re going to have to style features by hand. In OpenLayers, a style is a bare Javascript object with no required methods and a number of optional properties attached to either a layer as a whole or to a single feature (unstyled features inherit the style of the layer). A complete list of those style properties is given at the end of this chapter, but the meat of this section will be exploring best practices.

Styling your own features means creating a number of style objects and attaching those to the feature data or a whole layer. OpenLayers provides a way to both use constants and to use feature properties to style a layer. If the features don’t contain all the properties in the form you need to do your styling, pass the features through a pre-processing function that adds attributes to the feature containing the styling values:

function styleByCityAttributes(feature) { 
	var loColor = parseInt(“0x0000FF”)
	var hiColor = parseInt(“0xFF0000”)
	var v = feature.attributes.population;
	var minV = 1000.0;
	var maxV = 1000000.0;
	if (v > maxV) { v=maxV; }
	if (v < minV) { v=minV; } 
	var x = (v-minV);
	features.attributes.fillColor = 
		“#” + Math.round((v-minV) / (maxV-minV)).toString(16); 
	features.attributes.opacity = (v-minV) / (maxV-minV);
	if( v  < lt; 100000 ) { 
		features.attributes.graphicName = “circle”;
	} else if(v  < lt; 500000) { 
		features.attributes.graphicName = “square”;
	}
	if( feature.attributes.isCapital ) {
		features.attributes.graphicName = “star”;
	}
}

for(var f in features) { 
	if(features.hasOwnAttribute(f) {
		styleByCityAttributes(features[f]);
	}
}

Style objects can either take literal values or use feature attributes as their inputs using the notation "{property}":

var style = { 
	label : ‘${cityName}’,
	fillColor : ‘${fillColor}’,
	fillOpacity : ‘${opacity},
	strokeColor : ‘#fffccd’,
	strokeOpacity : 0.7,
	graphicName : ‘${graphicName}’,
	graphic : true
}

Doing all your attribute based styling in a single function is sensible for smaller datasets and less complex applications, but a more reusable way to do it is to define your styles piecemeal and assemble them. In this way, styles can be “built up” gradually. The following function creates a data driven styler object:

function DataDrivenStyler() { return {
 	style : { }
	add : function(styleAttr, func) {
		if(typeOf(func) === ‘function’) {
			funcs.push({attr : styleAttr, func : func});
			style[styleAttr] = “${“ + styleAttr “}”;
		}
		else {
			style[styleAttr] = func;
		}
 	}, 
 	applyStyle : function(layer) {
		var i, p, param, f, feature;
		for(f=0; f

The applyStyle method takes an OpenLayers.Layer.Vector and styles each feature individually. The add method takes a style attribute and a function for use by the styler to style that attribute. For every feature passed to the styler, the function is passed the feature’s associated data and should return a value. That value is assigned to the attribute named in the add function.

We use this object like this:

var featureLayer = //OpenLayers.Layer.Vector definition
var property = function(p) { return function(f) { return f[p]; } };
var pointSizeByDollars = //scale point size by feature property ‘dollars’
var fillColorByCompanies = //function blending fill color by feature property “num companies”

var fstyler = DataDrivenStyler();
fstyler.add(‘fillColor’, fillColorByNumCompanies);
fstyler.add(‘fillOpacity’, 0.7);
fstyler.add(‘label’, ‘${caption}’));
fstyler.add(‘pointRadius’, pointSizeByDollars);

fstyler.style(featureLayer.features)
map.addLayers([featureLayer]);

Here we have a layer, featureLayer, that we pass through our custom data-driven styler, fstyler. We create a number of functions including the trivial but useful constant and property functions that return either a constant value or an unmodified data value from the feature as the value for a style attribute.

Here, we modify from the default the fill color, fill opacity, text label, and point size based on three data attributes that come in all our features.

The cost of doing things this way might look on the face of things to be quite high, but Javascript optimizers are powerful and furthermore the cost of actually rendering a feature on the screen is much higher than calling a series of lightweight-functions to style each feature. The rewards of “functional programming” applied in this way are consistency and readability, and they outweigh the negatives for all but the more extreme cases. This technique is used to great effectiveness in the general visualization toolkit, Protovis

Semantic feature styling

When large groups of features all need to have the exact same style, the data-driven styler seems a bit overkill. Instead, you may want to define a number of custom style objects and assign them based on semantically meaningful categories of your data.

var fireTruckStyle = { externalGraphic: ‘/images/fireTruck.png’ }; 
var policeCarStyle = { externalGraphic: ‘/images/policeCar.png’ };
var blockedRoadSegment = { strokeColor: “#ffff00” };

var roadsLayer = // OpenLayers.Layer.Vector
var carsLayer = // OpenLayers.Layer.Vector

var x;
for(x=0; x

The following reference material is provided here in hopes that it will be useful, but the definitive reference can be found at OpenLayers.org

OpenLayers StyleMap attribute reference

Fill attributes

  • fill Boolean true for filled features, false for unfilled.
  • fillColor String HTML fill color.  Default is “#ee9900”.
  • fillOpacity Number Fill opacity (0-1).  Default is 0.4

Outline attributes

  • stroke Boolean True for stroked features, false for nonstroked.
  • strokeColor String HTML stroke color.  Default is “#ee9900”.
  • strokeOpacity Number Stroke opacity (0-1).  Default is 1.
  • strokeWidth Number Stroke width in pixels.  Default is 1.
  • strokeLinecap String Line cap type.  Default is “round”.  Options are butt | round | square
  • strokeDashstyle String Line dash style.  Default is “solid”.  Options are dot | dash | dashdot | longdash | longdashdot | solid

Rendering external graphics at points

  • externalGraphic String URL for an graphic for a point.
  • graphicWidth Number Width in pixels for re-sizing an externalGraphic. If not provided, the image width will be used.
  • graphicHeight Number Height in pxiels for re-sizing an externalGraphic. If not provided, the image height will be used.
  • graphicOpacity Number Opacity (0-1) for an externalGraphic.
  • graphicXOffset Number Pixel offset west-to-east from the feature location for placing an externalGraphic.
  • graphicYOffset Number Pixel offset north-to-south from the feature for placing an externalGraphic.
  • graphicTitle String Tooltip for an external graphic. Some browsers do not support this.
  • backgroundGraphic String URL to a graphic to be used as the background under an externalGraphic. This can be used for drop shadows.
  • backgroundGraphicZIndex Number The integer z-index value to use in rendering the background graphic. Higher z-indexes are “closer” to the user.
  • backgroundXOffset Number The x offset west-to-east from the feature location (not from the externalGraphic) for the background graphic.
  • backgroundYOffset Number The y offset north-to-south from the feature location (not the externalGraphic) for the background graphic.
  • backgroundHeight Number The height in pixels of the background graphic.  If not provided, the graphicHeight will be used.
  • backgroundWidth Number The width in pixels of the background width.  If not provided, the graphicWidth will be used.

Rendering points

  • pointRadius Number Point radius in pixels.  Default is 6.
  • rotation Number For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point or any point off center as specified by graphicXOffset and graphicYOffset.
  • graphicZIndex Number The integer z-index value to use when rendering the point. Use higher indices for bringing it closer to the user. The default is the feature layer’s z-index.
  • graphicName String Named graphic to use when rendering points.  Options are “circle” (default) | “square” | “star” | “x” | “cross” | “triangle”

Rendering feature labels

  • label String The text for an optional label.  For browsers that use the canvas renderer, this requires either fillText or mozDrawText to be available. This works in Firefox, Chrome, and Internet Explorer 8 and above.
  • labelAlign String Whee the insertion point is relative to the text.  It’s a two character string where the first character is the horizontal alignment, and the second gives the vertical alignment.
    • Horizontal alignment options: “l” | “c” | “r”.
    • Vertical alignment options: “t”=top, “m”=middle, “b”=bottom.  Not supported by the canvas renderer.
  • labelXOffset Number Pixel offset east-to-west from the feaature origin.
  • labelYOffset Number Pixel offset north-to-south from the feature origin.
  • labelSelect Boolean Whether or not labels will be selectable using SelectFeature or similar controls.  Default is false.
  • fontColor String The font color for the label.
  • fontOpacity Number Opacity (0-1) for the label.
  • fontFamily String The CSS font family for the label.
  • fontSize String The CSS font size for the label.
  • fontWeight String The CSS font weight for the label.
  • <

Miscellaneous attributes

  • graphic Boolean Whether or not to draw the feature graphic. This is useful if you only want to draw text, but don’t need an anchor point for it.
  • cursor String Default is “”.
  • pointerEvents String Default is “visiblePainted”.
  • display String If this is set to “none”, the feature will not be displayed at all. Useful for hiding or for marking features as deleted while maintaining undo-able state.

One thought on “Adding style to your OpenLayers

  1. Pingback: Openlayers: custom style map | Question and Answer

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>