【问题标题】:How to update MapboxGL.ShapeSource dynamically?如何动态更新 MapboxGL.ShapeSource?
【发布时间】:2019-07-15 18:40:30
【问题描述】:

使用react-native-mapbox-gl/maps,当SymbolLayer动态添加到ShapeSource时,似乎没有显示出来,或者ShapeSource没有更新。

这里是重现的例子:基于CustomIcon example,我用下面的代码替换了代码。要重现,只需 execute the examples,复制粘贴代码以替换 CustomIcon.js 示例中的现有代码。

import React from 'react';
import { View, Text } from 'react-native';
import MapboxGL from '@react-native-mapbox-gl/maps';

import sheet from '../styles/sheet';

import BaseExamplePropTypes from './common/BaseExamplePropTypes';
import Page from './common/Page';
import Bubble from './common/Bubble';

const styles = {
  icon: {
    iconAllowOverlap: true,
  },
  view: {
    width: 60,
    height: 60,
    borderColor: 'black',
    borderWidth: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
  text: {
    fontSize: 50
  }
};

const customIcons = ['????', '????', '????', '????', '????']

class CustomIcon extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      featureCollection: {
        type: 'FeatureCollection',
        features: [{
          type: 'Feature',
          geometry: {
            coordinates: [-73.970895, 40.723279],
            type: 'Point'
          },
          id: 1,
          properties: {
            customIcon: customIcons[0]
          }
        }]
     },
    };

    this.onPress = this.onPress.bind(this);
    this.onSourceLayerPress = this.onSourceLayerPress.bind(this);
  }

  onPress(e) {
    const feature = {
      type: 'Feature',
      geometry: e.geometry,
      id: Date.now(),
      properties: {
        customIcon: customIcons[this.state.featureCollection.features.length]
      }
    };

    this.setState(({ featureCollection }) => ({
      featureCollection: {
        type: 'FeatureCollection',
        features: [
          ...featureCollection.features,
          feature
        ]
      }
    }));
  }

  onSourceLayerPress(e) {
    const feature = e.nativeEvent.payload;
    console.log('You pressed a layer here is your feature', feature); // eslint-disable-line
  }

  render() {
    return (
      <Page {...this.props}>
        <MapboxGL.MapView
          ref={c => (this._map = c)}
          onPress={this.onPress}
          style={sheet.matchParent}
        >
          <MapboxGL.Camera
            zoomLevel={9}
            centerCoordinate={[-73.970895, 40.723279]}
          />

          <MapboxGL.ShapeSource
            id="symbolLocationSource"
            hitbox={{width: 20, height: 20}}
            onPress={this.onSourceLayerPress}
            shape={this.state.featureCollection}
          >
            {this.state.featureCollection.features.map((feature, ind) => (
              <MapboxGL.SymbolLayer
                id={"symbolLocationSymbols" + feature.id}
                key={feature.id}
                filter={['==', 'customIcon', customIcons[ind]]}
                minZoomLevel={1}
                style={styles.icon}
              >
                <View style={styles.view}>
                  <Text style={styles.text}>
                    {feature.properties.customIcon}
                  </Text>
                </View>
              </MapboxGL.SymbolLayer>
            ))}
          </MapboxGL.ShapeSource>
        </MapboxGL.MapView>

        <Bubble>
          <Text>Tap to add an icon</Text>
        </Bubble>
      </Page>
    );
  }
}

export default CustomIcon;

我们可以看到点击地图改变了状态,添加了一个特征,但是没有在地图上显示这个特征。 我们如何使ShapeSource 动态更新?

【问题讨论】:

    标签: reactjs react-native mapbox mapbox-gl-js mapbox-gl


    【解决方案1】:

    关于这个主题的全部讨论都在这里:https://github.com/react-native-mapbox-gl/maps/issues/248

    简而言之:我想将动态 SVG 用作 SymbolLayer(以便我可以更改颜色),但这是不可能的:给 SymbolLayer 任何子组件都不是正确的做法.

    我们需要将Images 与ShapeSource 和SymbolLayer 并行使用,因为Images 可以动态更新。

    这是一个代码示例:

    import React from 'react';
    import MapboxGL from '@react-native-mapbox-gl/maps';
    
    const myImages = {
      'image-1': 'path/to/image-1',
      'image-2': 'path/to/image-2'
    }
    
    const createFeature = ({ 
      showPin, 
      icon = 'image-1', // as long as any added feature has an icon belonging to the static myImages, it works.
      coordinates, 
      id 
    }) => ({
      // https://github.com/react-native-mapbox-gl/maps/blob/master/docs/ShapeSource.md -> shapeSource prop
      // https://geojson.org
      // this has a geoJSON shape
      type: 'Feature',
      id,
      properties: {
        showPin,
        icon
      },
      geometry: {
        type: 'Point',
        coordinates,
      }
    })
    
    class MyMarkers extends React.Component {
    
    
      state = {
        featureCollection: MapboxGL.geoUtils.makeFeatureCollection(),
      }
    
      componentDidMount() {
        this.updateFeatures()
      }
    
      componentDidUpdate(prevProps) {
        // update features based on any criteria
        if (conditionOnProps(prevProps, this.props)) this.updateFeatures() 
      }
    
      updateFeatures() {
    
        const featureCollection = MapboxGL.geoUtils.makeFeatureCollection()
    
        for (let feature of this.props.features) {
          MapboxGL.geoUtils.addToFeatureCollection(
            featureCollection,
            createFeature(feature)
          )
        }
    
        this.setState({ featureCollection });
      }
    
      onPress = (e) => {
        const feature = e.nativeEvent.payload;
        this.props.doAnythingWithPressedFeature(feature);
      }
    
      render() {
    
        return (
          <>
            <MapboxGL.Images images={myImages} />
            <MapboxGL.ShapeSource
              id='markersShape'
              shape={this.props.featureCollection}
              onPress={this.onPress}
            >
              <MapboxGL.SymbolLayer
                id='markersSymbol'
                filter={['==', 'showPin', true]}
                style={{
                  iconAllowOverlap: true,
                  iconImage: ['get', 'icon'],
                }}
              />
            </MapboxGL.ShapeSource>
          </>
        )
      }
    }
    
    export default MyMarkers;
    

    【讨论】:

      猜你喜欢
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多