You are here

OpenLayers making polygons interactive in Drupal 7

I have been working with OpenLayers 2.x in Drupal 7 where I needed polygons, loaded from a KML file, to link to Drupal pages when clicked. I ended up create a module that adds a new behaviour to the layer containing the polygons.

This post assumes that you known how to configure OpenLayers to display a map and add a KML layer on top of it. I'll use the KML file attached to this post, which contains the Danish administrative regions. You should be aware that KML files need an absolute URL as the file is read be the OpenLayers library in JavaScript on the client site. Start by creating a new KML layer and create a map with the layer.

You can download the KML file here

The next step is to create a module that defines a behaviour, which interact with the KML layer and capture mouse clicks inside the polygons defined by the layer. The behaviour will be configurable, so the polygon => URL mapping is defined in the OpenLayers UI. Start by creating a info file with the following information.

name = OpenLayers Polygon URL Mapping
description = OpenLayers behaviour that creates a polygon => URL mapping. So clicks inside polygons create a redirect to an URL.
core = 7.x
package = "Openlayers"
dependencies[] = openlayers

files[] = MODULENAME.module
files[] = includes/openlayers_behavior_kml_clicks.inc

The module file should contain a function that defines the behaviour(s) that this module provides to OpenLayers. It defines the behaviour's name, description and where to locate the class that is the behaviour.

function MODULENAME_openlayers_behaviors() {
  return array(
    'openlayers_behavior_region_click' => array(
      'title' => t('KML click'),
      'description' => t('Redirects to a URL when a KML polygon is clicked'),
      'type' => 'layer',
      'path' => drupal_get_path('module', 'MODULENAME') . '/includes',
      'file' => 'openlayers_behavior_kml_clicks.inc',
      'behavior' => array(
        'class' => 'openlayers_behavior_kml_click',
        'parent' => 'openlayers_behavior',
      ),
    ),
  );
}

Create a file named includes/openlayers_behavior_kml_clicks.inc which contains the class openlayers_behavior_kml_click which is inherited from openlayers_behavior as shown below. The class has three methods: options_init, options_form and render. The first two functions are used to display the configuration form for the behaviour, which is shown in the UI. In the render method the JavaScript file, which holds the actual code used to manipulate the map, is added.

class openlayers_behavior_kml_click extends openlayers_behavior {
 
  function options_init() {
    return array(
    );
  }

  function options_form($defaults) {
    // Only show available KML layers.
    $layers = array();
    foreach ($this->map['layers'] as $layer_name) {
      $layer = openlayers_layer_load($layer_name);
      if ($layer->data['layer_type'] == 'openlayers_layer_type_kml') {
        $layers[] = $layer_name;
      }
    }

    return array(
      'layername' => array(
        '#type' => 'select',
        '#options' => $layers,
        '#description' => t('Select layer to use'),
        '#default_value' => isset($defaults['layername']) ? $defaults['layername'] : NULL
      ),
      'features' => array(
        '#type' => 'textarea',
        '#description' => t('Enter the urls and the feature identifier. One on each line seprated => as PHP array syntaxt.'),
        '#default_value' => isset($defaults['features']) ? $defaults['features'] : NULL
      ),
    );
  }

  function render(&$map) {
    drupal_add_js(drupal_get_path('module', 'MODULENAME') . '/includes/js/openlayers_behavior_kml_click.js');
    return $this->options;
  }
}

Create the file js/openlayers_behavior_kml_click.js and add the code below. The code is explained in-line, but it basically adds a hover effect to the polygons and registrars click events in the polygons defined in the KML layer chosen.

(function($) {
Drupal.openlayers.addBehavior('openlayers_behavior_kml_click', function (data, options) {
// Place holder for the currently active feature.
var current_feature = undefined;

  // Get openlayers map object.
  var map = data.openlayers;

  // Parse the configuration into an array.
  var features = {};
  var lines = options.features.split(/\r\n|\r|\n/);
  for (var i in lines) {
    var parts = lines[i].split('=>');
    if (parts.length == 2) {
      features[parts[0].replace(/^\s+|\s+$/g,'')] = parts[1].replace(/^\s+|\s+$/g,'');
    }
  }

  // Get selected layer.
  var layer = map.getLayersBy('drupalID', options.layername)[0];

  // Polygon/feature callback when hovering over an polygon.
  var polygon_callback = function(e) {
    current_feature = e.feature.attributes.name;
  }

  // Callback when region/feature is clicked. It will redirect the browser
  // to the url defined in the configuration.
  var click_callback = function(e) {
    window.location = features[current_feature];
  }

  // Add click event to the layer.
  layer.events.register("click", layer, click_callback);

  // Added highlighting on layer hover.
  var highlightCtrl = new OpenLayers.Control.SelectFeature(layer, {
    hover: true,
    highlightOnly: true,
    renderIntent: "temporary",
    eventListeners: {
      featurehighlighted: polygon_callback
    }
  });
  map.addControl(highlightCtrl);
  highlightCtrl.activate();

});
})(jQuery);

If you want to change the color used to highlighting the polygons when hovering you can define a new style and select that as the temporary style in the maps configuration UI, For documentation about creating styles look in the docs folder that comes with the OpenLayers module.

Configuring the behaviour

Edit the map and active the behaviour and add configuration lines with this format KML name => URL. The KML polygon name can be found in the KML file under Placemark and the name element for each polygon in the file.

This is an example configuration for the KML file attached to this blog post.

Nordjylland => /node/2
Midtjylland => /node/3
Syddanmark => /node/4
Sjaelland => /node/5
Hovedstaden => /node/6

Files

References

Tags

Drupal 7 Openlayers JavaScript PHP

Comments

Thank you for posting this.

This is exactly what I need for my current project. Thank you for this awesome post. Perhaps you would like to post a link in the Drupal openlayers documentation on d.o.?

Add new comment