1

Is there any way to automatically style each feature read from a GeoJSON File and used as a source for a vectorlayer differently? I’ve attached a screenshot: This mess of green line features is more than confusing. It would be nice for each line to have a different color randomly assigned to it. Thanks for your help!

enter image description here

Edit: Added Code

Here you find the relevant Code I’m using for this representation. You can see that I define green as the color für LineStrings, but I’m wondering how I can automate the allocation of different colors to LineStrings.

// load GeoJSON with > 2000 Line Features
var fullGeoJSON = require("./data/datafile.json");
// Style function to be called in Layer definition, uses Styles defined in var styles
var styleFunction = function (feature) {
    return styles[feature.getGeometry().getType()];
};
// Define Style (one for all)
var styles = {
    "Point": new Style({
        image: image
    }),
    "LineString": new Style({
        stroke: new Stroke({
            color: "green",
            width: 3
        })
    }),
};
// Define Source
var geoSource = new VectorSource({
    features: new GeoJSON().readFeatures(fullGeoJSON, {
        featureProjection: "EPSG:3857"
    })
});
// Define Layer
var baseLayer = new VectorLayer({
    source: geoSource,
    style: styleFunction
});
// Define Map
const mainMap = new Map({
    target: "map-container",
    layers: [baseLayer],
    view: initialView
});
karkraeg
  • 445
  • 4
  • 18
  • You should post the relevant code here. Otherwise it is not possible for the community to see where the problem is. – Carles Nov 30 '18 at 08:11
  • Hi @Carles, I added the relevant Code. – karkraeg Nov 30 '18 at 08:17
  • What I would do is to modify styleFunction so, instead of returning the fixed predeffined styles from the var "styles", it can check the data type. If the Type=="Point" it returns the default style, otherwise, it returns a custom generated style with a random color. As a summary, when you load the file, every item is style using "style: styleFunction", so it calls to function "styleFunction" for every point, if I'm not wrong. This function reads the type and return the style from the array according to that type. What I propose is to have runtime generated data instead of using the array. – Carles Nov 30 '18 at 08:31
  • 2
    A style function is called repeatedly as the map is zoomed, panned, etc. Returning a random color in each call of the function might result in undesirable changes. I would suggest iterating once through the all features and setting a random color property in each which could be read in the style function `color: feature.get('color')` (similar to how feature names are used in text labels). – Mike Nov 30 '18 at 12:29
  • @Mike how would I get random colors? – karkraeg Dec 02 '18 at 19:14
  • You could set up an array of colors which would be suitable for your map e.g. `var colors = ['red','green','blue','yellow','cyan','magenta', .... ];` then use the js random function to select a random entry from your array `var randomColor = colors[Math.floor(Math.random() * colors.length)];` – Mike Dec 02 '18 at 19:29
  • thanks! I found https://stackoverflow.com/questions/1484506/random-color-generator – will look into using Hexcolors in OpenLayers. – karkraeg Dec 03 '18 at 21:08
  • For colors, check this out too: https://gka.github.io/chroma.js/ – pavankguduru Dec 05 '18 at 11:01
  • That’s nice @pavankguduru, I can image using the `chroma.scale` method for my purpose. I’m hoping to have time to work on this and then post an answer to my question based on the help I already got! – karkraeg Dec 05 '18 at 15:04
  • Sorry, but can anyone point me in the right direction: How do I iterate over all features? I read them like in `var geoSource = new VectorSource`… – karkraeg Dec 07 '18 at 17:47
  • 1
    `VectorSource.forEachFeature(function(feature) { randomColor = ????; feature.set('color', randomColor)'; });` – Mike Dec 09 '18 at 19:32

1 Answers1

0

I figured it out thanks to all the help from your comments:

  1. Load chroma.js into your project (I use npm and webpack and after installing it with npm I require chroma like this: var chroma = require("chroma-js");)
  2. Define a randomize function:

    function randomize() {
        geoSource.forEachFeature(function (feature) {
            var scale = chroma.scale(["#731422", "#1CBD20", "#1CA1FF"]).mode("lch").colors(300); // Define color scale
            var randomColor = scale[Math.floor(Math.random() * scale.length)]; // select a random color from color scale
            var randomStyle = new Style({
                stroke: new Stroke({
                    color: randomColor,
                    width: 5
                })
            }); // define a style variable
            feature.setStyle(randomStyle); // set feature Style
        });
    }
    
  3. call the function once and whenever the layer chnages: randomize();

  4. "Define" Layer, this time without a style:

    var baseLayer = new VectorLayer({
        source: geoSource
    });
    

enter image description here

karkraeg
  • 445
  • 4
  • 18