3 votes

deck.gl GeoJsonLayer : mise à jour de la couleur de l'élément au clic

J'utilise le GeoJsonLayer de deck.gl pour afficher les régions sur une carte. Grâce à un événement, j'ai pu rendre ces régions sélectionnables. Ce qui me pose problème, c'est de changer la couleur d'un élément dans la sélection d'éléments après avoir cliqué dessus.

c'est la fonction de la couche de rendu (adapté de aquí )

_renderLayers(props) {
  const { geofeats } = props;

return [
  new GeoJsonLayer({
    id: 'geojson',
    data: geofeats,
    opacity: 0.8,
    stroked: true,
    filled: true,
    extruded: true,
    wireframe: true,
    getElevation: f => 10000, 
    getFillColor: f =>
    {
        if(f.properties.selected)
        {
            return  [200, 200, 100];
        } else return  [200, 100, 150];

    },
    getLineColor: [255, 255, 255],
    pickable: true,
    onHover: this._onHover, 
    onClick: this._onClick
  })
];
}

Le problème est que, lorsque je mets à jour l'état de sélection d'une caractéristique dans la collection de caractéristiques via setState(), le rendu n'est pas mis à jour bien que le changement d'état soit représenté dans les données

c'est ainsi que je relaie l'objet 'geofeats' :

  render() {
  const {features} = this.state;

  const {mapStyle = 'mapbox://styles/mapbox/light-v9'} = this.props;

return (
  <DeckGL
    layers={this._renderLayers({geofeats: features})}
    effects={this._effects}
    initialViewState={INITIAL_VIEW_STATE}
    controller={true}
  >
    <StaticMap
      reuseMaps
      mapStyle={mapStyle}
      preventStyleDiffing={true}
      mapboxApiAccessToken={MAPBOX_TOKEN}
    />

    {this._renderTooltip}
  </DeckGL>
);
}

J'ai essayé via setState au lieu de via props - mais le résultat est le même. La collection de caractéristiques est transmise à la GeoJsonLayer mais n'est jamais mise à jour.

Quelqu'un pourrait-il me dire ce que je fais mal ?

Mise à jour : exemple de gist avec reproduction des erreurs : https://gist.github.com/jaronimoe/efdbb58b3f52c2aac63362a921802cfe

3voto

John Ruddell Points 6445

Votre problème est double.

Tout d'abord, vous n'attribuez jamais d'ID unique à chaque caractéristique, ce qui signifie que toutes les caractéristiques sont affectées à la catégorie sélectionnée lorsque vous survolez un élément. Cela est dû au fait que dans setFeatureSelected, vous comparez undefined == undefined aka ( currentID == selectedId ). À titre d'information, vous devez choisir par défaut le triple égal.

Deuxièmement, vous devez dire à votre GeoJsonLayer comment mettre à jour les couleurs. Voici les changements que vous devrez faire :

function setFeatureSelected(features, selfeat) {
  let selectedID = selfeat.properties.id;
  for (let i = 0; i < features.features.length; i++) {
    let currentID = features.features[i].properties.id;

    if (selectedID === currentID) {
      features.features[i].properties.selected = true;
    } else {
      // Make sure to update the others to be false, so that way only one is ever selected
      features.features[i].properties.selected = false;
    }
  }

  return features;
}

Ensuite, vous voulez mettre à jour initFeatureSelected pour injecter des identifiants. Pour l'instant, j'utilise simplement l'index dans le tableau, mais vous pouvez utiliser quelque chose de plus explicite si vous le souhaitez.

function initFeatureSelected(features) {
  for (let i = 0; i < features.features.length; i++) {
    features.features[i].properties.selected = false;

    // Track each feature individually with a unique ID.
    features.features[i].properties.id = i;
  }

  return features;
}

La dernière partie dont vous avez besoin est de dire à la GeoJsonLayer que vous avez de nouvelles valeurs pour recalculer la getFillColor fonction. Ceci est fait avec updateTriggers où vous passez la valeur de la chose qui détermine si la couleur doit changer. Dans votre cas, il s'agit de l'identifiant sélectionné de votre fonctionnalité.

new GeoJsonLayer({
  id: 'geojson',
  data,
  opacity: 0.8,
  stroked: false,
  filled: true,
  extruded: true,
  wireframe: true,
  getElevation: 50, //Math.sqrt(f.properties.valuePerSqm) * 10,
  getFillColor: d => d.properties.selected ? [100, 105, 155] : [55, 205, 155], //COLOR_SCALE(f.properties.growth),
  getLineColor: [255, 255, 255],
  updateTriggers: {
    getFillColor: [
      this.state.hoveredObject
        ? this.state.hoveredObject.properties.id
        : null
    ]
  },
  pickable: true,
  onHover: this._onHover
})

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X