Vue2leaflet: Recalculate the style of a GeoJSON layer based on reactive variables change

Created on 20 Dec 2017  路  11Comments  路  Source: vue-leaflet/Vue2Leaflet

I'm sorry that I write a question here, but for some reason, StackOverflow says there is no tag for Vue2Leaflet, and I don't have enough reputation to create a new tag. This might actually be a bug / enhancement so hopefully it will be ok.

I have a Vue2Leaflet map with a GeoJSON layer. This layer has a style that depends on additional data from the features in the GeoJSON data, and also on an external parameter (the color depends on data, and the data to show depends on a selection of the user).

When I change the external property, the style doesn't update reactively. Is there a way to tell the style to recalculate itself?

I tried to access the mapObject and to re-set the style property (even though it's not strictly necessary) but I got an error saying the mapObject was undefined.

My code looks something like this:

    <v-map ...>
        <v-tilelayer ... />
        <v-geojson-layer ref="geojsonLayer" :options="geoOptions" 
            :geojson="geojson" />
    </v-map>

with the style function (simplified):

    geoOptions: {
        style: feature => {
            if (this.var1 === '') return {}
            let data = feature.properties.data
            if (data[this.var1] === undefined) return {}
            if (data[this.var1][this.var2] === undefined) return {}
            return {
                fillColor: scale(data[this.var1][this.var2]).hex()
                ...
            }
        }
    }

where scale() is a chroma.js colorscale that depends on the value of this.var1. What I would like to have is that whenver this.var1 or this.var2 change (they are reactive variables), the style of the features will get re-evaluated.

I hope I expressed my problem clearly.

Thank you very much!
Omri

Most helpful comment

@cordlesstuba you can do something like this:
1) create computed property that changes anytime ANY of the properties that you are interested in change
2) add a watcher on such property
3) add a code like this in the watcher body

updateGeoJsonStyle (newStyle) {
      this.$nextTick(() => {
        if (this.$refs.geoJson && this.$refs.geoJson.mapObject) {
          this.$refs.geoJson.mapObject.eachLayer((layer) => {
              layer.setStyle(newStyle);
          });
        }
      });
    }

All 11 comments

Hi @omrihar,

Did you try to put geoOption as a computed property?

Micka

Hi @KoRiGaN,

I haven't, but I'll try and see how this works (I'm doing some extensive rewriting so it might be a while until I manage to get to this part).

Omri

But as far as I know, you should not use 'options' for a reactive style.

The options will use L.setOptions in Leaflet which updates options data but is not visible on the map.

The best way would be to use the setStyle function for each feature.
Never tried and not sure how to make it works with GeoJSON though.

Let me know if you find a good solution.

What I wound up doing was to create a different Geojson object for each dataset I had (I'm basically plotting a heatmap on top of a map) and switching the geojson object when I want to display different datasets.

It's probably not the most efficient solution but so far seems to work well for my purposes. I also only have features for those areas where I display a value, so the total number of objects in the feature collection is not too high. If I find a different solution I'll let you know.

Cheers,
Omri

I had the same issue but with mouse hovering and managed to implement the setStyle option onEachElement, like:

function onEachFeature (feature, layer) {
    layer.on('mouseover', function (e) {
        e.target.setStyle({
            fillColor: '#ff0033',
        });
    });
    layer.on('mouseout', function (e) {
        e.target.resetStyle()
    });
}

Only the resetStyle does not work yet

The way @KoRiGaN mentioned works:

onEachFeature(feature, layer) {
      // set style for each feature
      const color = getColor(feature.properties.color)
      layer.setStyle({
        color: color,
        fillColor: color,
        fillOpacity: 0.1,
      })
}

Although I haven't quite figured out why we can't set the geojson style as the vector layers

up ! Still need to be to Recalculate the style of a GeoJSON layer based on reactive variables change !

Thanks

@cordlesstuba you can do something like this:
1) create computed property that changes anytime ANY of the properties that you are interested in change
2) add a watcher on such property
3) add a code like this in the watcher body

updateGeoJsonStyle (newStyle) {
      this.$nextTick(() => {
        if (this.$refs.geoJson && this.$refs.geoJson.mapObject) {
          this.$refs.geoJson.mapObject.eachLayer((layer) => {
              layer.setStyle(newStyle);
          });
        }
      });
    }

Thanks it works !

@cordlesstuba Or use options-style prop. Example

Hi!

You can use the following code inside a computed property:

onEachFeatureFunction() {
      return (feature, layer) => {
          layer.on({
            mouseover(e){
              this.setStyle({
                  fillColor: '#ff0000',
                  color: '#ff0000'
              });
            },
            mouseout(e){
              this.setStyle({
                  fillColor: '#bf9946',
                  color: '#bf9946'
              });
            },
        }
    })
 }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tiltec picture tiltec  路  4Comments

zaqisilverano picture zaqisilverano  路  4Comments

carlmjohnson picture carlmjohnson  路  4Comments

mits87 picture mits87  路  3Comments

lufias picture lufias  路  3Comments