metacubed metacubed - 2 months ago 23
Javascript Question

Use CSS for Vector Layer styling in OpenLayers

I am using OpenLayers to show multiple Vector layers based on some API calls. Currently, I style these layers using a StyleMap-Style combination for each layer, like so:

var layer1Style = new OpenLayers.Style({
strokeColor: "blue",
strokeWidth: 2,
strokeOpacity: 0.8
});
var layer1 = new OpenLayers.Layer.Vector("Layer 1", {
strategies: [new OpenLayers.Strategy.Fixed()],
styleMap: new OpenLayers.StyleMap({
"default": layer1Style
})
});
map.addLayer(layer1);

var layer2Style = ...
var layer2 = ...
map.addLayer(layer2);

// and so on


Is there a way to pull out these per-layer styles into a CSS file? I really do not want to declare these inline in JS for every layer - CSS/LESS is much better at abstracting these out.

Note that this is a dummy snippet - the actual code is more complex and uses async API calls to create layers on the fly.

I am currently using OL 2.13.x.

This question is similar, but deals with a different, very specific scenario.

Answer

You can use a css parser and generate JSON data for your layer style . JSCSSP is a good library for parsing css . I've written a small wrapper class for your problem using JSCSSP .

In the constructor of the Parser class , make a get request to the css file using XMLHttpRequest and parse the css data with CSSParser.parse() .

function Parser(url)
{
  var xmlHttp = new XMLHttpRequest();
  xmlHttp.open( "GET", url, false );
  xmlHttp.send();

  this.cssData = xmlHttp.responseText;
  var cssParser = new CSSParser();
  this.sheet = cssParser.parse(this.cssData, false, true);  
}

Add a method to the Parser class which searchs for the given rule name in the css file and generates json data from that rule .

Parser.prototype.parse = function(element)
{
  var result = {};

  var rules = this.sheet.cssRules;
  for (var i = 0; i < rules.length; i++) 
  {      
    if (rules[i].mSelectorText == element )
    {
      for (var j = 0; j < rules[i].declarations.length; j++)   
      {
        var value = rules[i].declarations[j].valueText;

        if (isNaN(Number(value)))            
          result[rules[i].declarations[j].property] = value;
        else
          result[rules[i].declarations[j].property] = Number(value);

      }   
    }
  }
  return result;      
}

Example usage :

test.css

#layer1{
    strokeColor: blue;
    strokeWidth: 2;
    strokeOpacity: 0.8;
}

javascript file

var parser = new Parser("test.css");

var layer1 = new OpenLayers.Layer.Vector("Layer 1", {
  strategies: [new OpenLayers.Strategy.Fixed()],
  styleMap: new OpenLayers.StyleMap({
    "default": new OpenLayers.Style(parser.parse("#layer1"))
  })
});

You can change return value of parse method to

return new OpenLayers.Style(result); 

to have a cleaner syntax while constructing a OpenLayers layer like this

"default": parser.parse("#layer1")

do not forget to include JSCSSP javascript file .