There are some controls, such as SelectFeature
, ModifyFeature
, or EditingToolbar
, which change the style of the feature depending on its current state, that is, if it is selected or is currently being edited. How does OpenLayers manage this? The answer is, through the render intents:
This recipe shows how we can modify the styles used for each render intent to change the look of our applications.
This way, features will be drawn on the map using blue instead of orange. Temporary features, those that are going to be created, will be drawn using green. Finally, those features that are selected, or are in the middle of the modification process, will be drawn using orange.
div
element to hold the map instance:<div id="ch07_rendering_intents" style="width: 100%; height: 95%;"></div>
<script type="text/javascript"> // Create the map using the specified DOM element var map = new OpenLayers.Map("ch07_rendering_intents"); var osm = new OpenLayers.Layer.OSM(); map.addLayer(osm); map.setCenter(new OpenLayers.LonLat(0,0), 2)
var defaultStyle = new OpenLayers.Style({ fillColor: "#336699", fillOpacity: 0.4, hoverFillColor: "white", hoverFillOpacity: 0.8, strokeColor: "#003366", strokeOpacity: 0.8, strokeWidth: 2, strokeLinecap: "round", strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, pointRadius: 6, hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", cursor: "inherit" }); var selectStyle = new OpenLayers.Style({ fillColor: "#ffcc00", fillOpacity: 0.4, hoverFillColor: "white", hoverFillOpacity: 0.6, strokeColor: "#ff9900", strokeOpacity: 0.6, strokeWidth: 2, strokeLinecap: "round", strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, pointRadius: 6, hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", cursor: "pointer" }); var temporaryStyle = new OpenLayers.Style({ fillColor: "#587058", fillOpacity: 0.4, hoverFillColor: "white", hoverFillOpacity: 0.8, strokeColor: "#587498", strokeOpacity: 0.8, strokeLinecap: "round", strokeWidth: 2, strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, pointRadius: 6, hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", cursor: "inherit" });
StyleMap
instance that holds the three styles created as three different render intents:var styleMap = new OpenLayers.StyleMap({ 'default': defaultStyle, 'select': selectStyle, 'temporary': temporaryStyle });
StyleMap
instance:var vectorLayer = new OpenLayers.Layer.Vector("Features", { styleMap: styleMap }); map.addLayer(vectorLayer);
var editingControl = new OpenLayers.Control.EditingToolbar(vectorLayer); var modifyControl = new OpenLayers.Control.ModifyFeature(vectorLayer, { toggle: true }); editingControl.addControls([modifyControl]); map.addControl(editingControl); </script>
Every vector layer can have an OpenLayers.StyleMap
instance associated with it. On its own, a StyleMap
instance stores one or more references to the OpenLayers.Style
instances, each one of which acts as a render intent:
var styleMap = new OpenLayers.StyleMap({ 'default': defaultStyle, 'select': selectStyle, 'temporary': temporaryStyle });
Every Style
instance stores information about a style, and usually they are created from a symbolizer hash, as in this recipe:
var defaultStyle = new OpenLayers.Style({ fillColor: "#336699", fillOpacity: 0.4, hoverFillColor: "white", hoverFillOpacity: 0.8, strokeColor: "#003366", strokeOpacity: 0.8, strokeWidth: 2, strokeLinecap: "round", strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, pointRadius: 6, hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", cursor: "inherit" });
Here we have defined a new style for the three render intents: default
, select
, and temporary
, which are well known render intents used by most of the controls.
A StyleMap
can store as many render intents as we desire, we are not limited to these three commonly used render intents. For example, we can define render intents such as red
or hidden
, and associate a Style
for them that renders features in red or not display them at all.
The render intents such as default
, select
, and temporary
, are used extensively by many components within OpenLayers. This way, when a feature is rendered, the default
style is used. When a feature is selected using the OpenLayers.Control.SelectFeature
control, the select
render intent is used to render the features. And when we are creating a new feature with OpenLayers.Control.EditingToolbar
(which internally uses OpenLayers.Control.DrawFeature
), the control renders the feature using the style defined on the temporary
render intent.
So, creating new render intents is no problem. In addition, we can create our custom controls and let them decide which render intent the layer must use to render the features.
Finally, let's briefly describe the code used to create the panel with the controls.
First, we have created an OpenLayers.Control.EditingToolbar
instance:
var editingControl = new OpenLayers.Control.EditingToolbar(vectorLayer);
This is an OpenLayers.Control.Panel
control containing buttons that activates/deactivates some OpenLayers.Control.DrawFeature
controls. Next, we have created an OpenLayers.ControlModifyFeature
instance, which is a single control and we have added it to the EditingToolbar control so that it becomes visible as a new button:
var modifyControl = new OpenLayers.Control.ModifyFeature(vectorLayer, { toggle: true }); editingControl.addControls([modifyControl]);
In the screenshot, the ModifyFeature
control is represented by the cross icon.
The process to style and render a feature is complex. The following lines summarize the main steps involved in the feature styling process.
For each feature, a vector layer must render the following:
OpenLayers.Layer.Vector.drawFeature(feature, style)
is called. It accepts two parameters: the feature
to be drawn and the style
to be used. It can be a symbolizer or a render intent string.style
property, it is used to render the feature.style
property, it is used to render the feature.style
argument is provided and it is a style symbolizer, then it is used to render the feature.style
is a render intent string, then a symbolizer is created from the Style
property associated to the render intent using the createSymbolizer
method. This is where feature attributes are merged within the symbolizer.13.59.227.82