Playing with StyleMap and the render intents

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:

Playing with StyleMap and 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.

How to do it...

  1. Create a new HTML file and add the OpenLayers dependencies. The first step is to add the div element to hold the map instance:
    <div id="ch07_rendering_intents" style="width: 100%; height: 95%;"></div>
  2. In the JavaScript section, initialize the map instance, add a base layer, and center the viewport:
    <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)
  3. Now we are going to create three different styles:
        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"
        });
  4. After this, create a StyleMap instance that holds the three styles created as three different render intents:
        var styleMap = new OpenLayers.StyleMap({
            'default': defaultStyle,
            'select': selectStyle,
            'temporary': temporaryStyle
        });
  5. Now we can create a vector layer using the previous StyleMap instance:
        var vectorLayer = new OpenLayers.Layer.Vector("Features", {
            styleMap: styleMap
        });
        map.addLayer(vectorLayer);
  6. Finally, we are going to add some controls to the map to allow the addition of new features and modification of the existing ones:
        var editingControl = new OpenLayers.Control.EditingToolbar(vectorLayer);
        var modifyControl = new OpenLayers.Control.ModifyFeature(vectorLayer, {
            toggle: true
        });
        editingControl.addControls([modifyControl]);
        map.addControl(editingControl);
    </script>

How it works...

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.

Tip

By setting the property display to "none" on the style's symbolizer hash, we can hide features. This is usually used in the delete render intent.

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]);
How it works...

In the screenshot, the ModifyFeature control is represented by the cross icon.

There's more...

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:

  • The method 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.
  • If the feature has a style property, it is used to render the feature.
  • Otherwise, if the vector layer has a style property, it is used to render the feature.
  • Otherwise, if the style argument is provided and it is a style symbolizer, then it is used to render the feature.
  • If the 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.

See also

  • The Styling features using symbolizers recipe
  • The Improving style using StyleMap and the replacement of feature's attributes recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.227.82