Реактивный буклет стиль геоджона, адаптированный под каждую особенность - PullRequest
0 голосов
/ 25 апреля 2018

Я новичок в реакции и пытаюсь превратить мою карту листовки в компонент реактив-листовки.

Компонент состоит из слоя плиток и слоя геоджон (коллекция объектов полигонов).

Я могу получить их в своем приложении, но не могу понять, как создать стиль для слоя геоджон, в котором цвет полигонов зависит от свойства каждого полигона.Более того, в какой-то момент пользователь должен иметь возможность выбрать свойство, используемое для стилизации полигонов.

Вот код, который у меня есть:

import React, { Component } from 'react';
import logo from './logo.svg';
import { Map, TileLayer, Marker, Popup, GeoJSON } from 'react-leaflet';
// the geojson feature collection is in there
import heatmap from './heatmap.json';
// the colormaps are in there
import material_design_colors  from './material_design_colors.json';

import './App.css';

class MyHeatMap extends Component {
  state = {
    lat: 37.8,
    lng: -96.0,
    zoom: 4,
    segment: "C_00",
    polygonFillColor: "pink",
    constant_range: [-10.0, 10.0],
  }
  // get the geoJson containing the heatmap
  getGeoJson(){
      return heatmap;
  }

  getColor(d) {
    // now uses palette from google material design: https://material.io/guidelines/style/color.html#color-color-palette
    var material_design_color_idx = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900"]
    var palette = new Array(material_design_color_idx.length)
    var i 
    for (i=0 ; i < material_design_color_idx.length ; i++){
        palette[i] = material_design_colors[this.state.polygonFillColor][material_design_color_idx[i]]
    }
    for (i=1 ; i <= palette.length; i++){
        // values of the property are between -10,0 and 10.0
        if (d < -10.0 + i * (10.0 - (-10.0))/palette.length){
        return palette[i-1]
    }
    }
  };

  style(feature) {
    return {
        // the fillColor is adapted from a property which can be changed by the user (segment)
        fillColor: this.getColor(feature.properties.scores[this.state.segment]),
        weight: 0.3,
        //stroke-width: to have a constant width on the screen need to adapt with scale 
        opacity: 1,
        color: material_design_colors[this.state.polygonFillColor]["400"],
        dashArray: '3',
        fillOpacity: 0.5
    };
  };

  render() {
    const position = [this.state.lat, this.state.lng]

    return (
      <Map center={position} zoom={this.state.zoom}>
        <TileLayer
          attribution="spatial.ai"
          url="uri of the mapbox tile layer"
        />

    <GeoJSON data={this.getGeoJson()} style={this.style()}></GeoJSON>
      </Map>
    )
  }
}


class App extends Component {
  constructor(props) {
    super();
  }
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <MyHeatMap/>
      </div>
    );
  }
}



export default App;

Конечно, это не работает, но яЯ не могу понять, как правильно внедрить мою функцию стиля, в частности, getColor в реактивную листовку.

Я начинаю с рабочего примера в javascript / листовке (без реакции), поэтому у меня может быть совершенно неправильная стратегия.Любые идеи очень приветствуются.

1 Ответ

0 голосов
/ 26 апреля 2018

Сначала убедитесь, что ваши файлы material_design_colors.json и heatmap.json экспортируют переменную.Для этого измените имена файлов на .js с .json т.е.

// in material_design_colors.js
var material_design_colors = [{...},
                              {...}];

module.exports = material_design_colors;    

// in heatmap.js
var heatmap= [{...},
             {...}];

module.exports = heatmap; 

Теперь добавьте конструктор в ваш компонент MyHeatMap и свяжите в нем ваши методы.измените атрибут стиля слоя GeoJSON, как показано в приведенном ниже коде.

import React, { Component } from 'react';
import { Map, TileLayer, Marker, Popup, GeoJSON } from 'react-leaflet';
import heatmap from './heatmap.js';
import material_design_colors from './material_design_colors.js';

class MyHeatMap extends Component {
    constructor(props) {
        super(props);

        this.state = {
            lat: 37.8,
            lng: -96.0,
            zoom: 4,
            segment: "C_00",
            polygonFillColor: "pink",
            constant_range: [-10.0, 10.0],
        }

        this.getColor = this.getColor.bind(this);
        this.style = this.style.bind(this);
    }

    // get the geoJson containing the heatmap
    getGeoJson() {
        return heatmap;
    }

    getColor(d) {
        // now uses palette from google material design: https://material.io/guidelines/style/color.html#color-color-palette
        var material_design_color_idx = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900"]
        var palette = new Array(material_design_color_idx.length)
        var i
        for (i = 0; i < material_design_color_idx.length; i++) {
            palette[i] = material_design_colors[this.state.polygonFillColor][material_design_color_idx[i]]
        }
        for (i = 1; i <= palette.length; i++) {
            // values of the property are between -10,0 and 10.0
            if (d < -10.0 + i * (10.0 - (-10.0)) / palette.length) {
                return palette[i - 1]
            }
        }
    };

    style(feature) {
        return {
            // the fillColor is adapted from a property which can be changed by the user (segment)
            fillColor: this.getColor(feature.properties.scores[this.state.segment]),
            weight: 0.3,
            //stroke-width: to have a constant width on the screen need to adapt with scale 
            opacity: 1,
            color: material_design_colors[this.state.polygonFillColor]["400"],
            dashArray: '3',
            fillOpacity: 0.5
        };
    };

    render() {
        const position = [this.state.lat, this.state.lng]

        return (
            <Map center={position} zoom={this.state.zoom}>
                <TileLayer
                    attribution="spatial.ai"
                    url="uri of the mapbox tile layer"/>

                <GeoJSON data={this.getGeoJson()} style={this.style}></GeoJSON>
            </Map>
           )
       }
    }

    export default MyHeatMap;

Здесь я переместил компонент MyHeatMap в новый файл MyHeatMap.js в той же папке.
Теперь ваш App.js будет выглядетькак это,

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import MyHeatMap from './MyHeatMap';

class App extends Component {
    constructor(props) {
        super();
    }
    render() {
        return (
            <div className="App">
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <h1 className="App-title">Welcome to React</h1>
                </header>
                <MyHeatMap />
            </div>
        );
    }
}

export default App;
...