【问题标题】:deck.gl GeoJsonLayer: update feature color on clickdeck.gl GeoJsonLayer:点击时更新特征颜色
【发布时间】:2019-09-08 18:33:08
【问题描述】:

我正在使用 deck.gl GeoJsonLayer 在地图上显示区域。 通过一个事件,我能够使这些区域可选。 我正在努力解决的问题是点击后更改特征选择中的特征颜色。

这是渲染层函数(改编自here

_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
  })
];
}

问题是,当我通过 setState() 更新特征集合中特征的选择状态时,即使数据中表示状态更改,渲染也不会更新..

这就是我传递“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>
);
}

我通过 setState 而不是通过 props 尝试了它 - 但结果是一样的。特征集合被移交给 GeoJsonLayer 但从未更新。

谁能告诉我,我做错了什么?

更新:带有错误再现的要点示例:https://gist.github.com/jaronimoe/efdbb58b3f52c2aac63362a921802cfe

【问题讨论】:

  • 当你在特征集合中更新选择状态时,你的意思是你用所选项目的不同颜色属性更新你的 geojson 的属性吗?
  • 猜测为什么它没有更新可能是你的 geojson 的 id 字段没有改变,或者你的数据对象的签名可能没有改变(内存中的位置)。您可以尝试更新这些以查看是否有帮助
  • @JohnRuddell 我更新了相应 geojson 功能的“selected”属性:getFillColor: f => { if(f.properties.selected) { return [200, 200, 100]; } 否则返回 [200, 100, 150]; },但似乎 getFillColor 没有重新触发..您知道成功触发重绘的代码示例吗?
  • 我认为您需要更改geojson。更新它的属性。
  • 这就是我正在做的 - geojson 属性已更改,但未反映在颜色中/颜色未更新。

标签: reactjs deck.gl


【解决方案1】:

您的问题有两个方面。

首先,您永远不会为每个功能分配一个唯一的 ID,这最终意味着当您悬停一个项目时,每个功能都将被分配给选中。这是因为在 setFeatureSelected 中您正在比较 undefined == undefined aka (currentID == selectedId)。顺便说一句,您应该默认为三等式

其次,您需要告诉您的GeoJsonLayer 如何更新颜色。以下是您需要进行的更改:

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;
}

然后您想更新initFeatureSelected 以实际注入ID。现在我只是使用数组中的索引,但如果你愿意,你可以使用更明确的东西

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;
}

您需要的最后一部分是告诉GeoJsonLayer 您有新值来重新计算getFillColor 函数。这是通过updateTriggers 完成的,您可以在其中传递确定颜色是否应该改变的事物的值。在您的情况下,哪个是您的功能的选定 ID

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
})

【讨论】:

  • 谢谢你,现在我终于让它工作了!顺便说一句,它也可以通过显然指向 this.state.hoveredObject.properties 来工作 - 但我永远不会想到指向实际悬停的对象而不是整个功能集合。 (很抱歉缺少 ID - 它们实际上在我的数据中,但我切换到演示数据以避免上传我的 geojson 文件......应该检查一下。)
  • 别担心!在项目和演示之间的翻译中丢失了一些东西。很高兴我能帮你弄清楚! :) 但我建议您指向updateTriggers 中的 ID。这样一来,您就有一个明确的值可供 deck.gl 进行比较。而不是一个对象或它在内存中的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-05
  • 2015-08-24
相关资源
最近更新 更多