TopoJSON в листовке через Omnivore: свойства чтения

Следуя руководству по картограммам в Leaflet, я понял, что преобразование Shapefile > GeoJSON создает очень большой файл. TopoJSON оказался лучшей альтернативой, за исключением невозможности доступа к свойствам каждой геометрии. Я объединил данные из https://github.com/centraldedados/violencia-domestica в Файл TopoJSON, преобразованный из шейп-файла, структурированный как так:

{
  "transform": {
    "scale": [
      0.0025081552497290688,
      0.0012125352320998587
    ],
    "translate": [
      -31.26818656921381,
      30.03017616271984
    ]
  },
  "objects": {"PRT_adm1": {
    "geometries": [
      {
        "type": "Polygon",
        "arcs": [[
          0,
          1,
          2,
          3,
          4
        ]],
        "properties": {
          "ENGTYPE_1": "District",
          "ISO": "PRT",
          "NL_NAME_1": null,
          "HASC_1": "PT.EV",
          "ID_0": 182,
          "NAME_0": "Portugal",
          "TYPE_1": "Distrito",
          "ID_1": 1,
          "NAME_1": "Évora",
          "CCN_1": 0,
          "CCA_1": null,
          "dgai_violencia_domestica_2008_2014": {
            "Valores": [
              {
                "Ano": "2009",
                "Entidade": [
                  {"GNR": "216"},
                  {"PSP": "171"}
                ]
              },
              {
                "Ano": "2010",
                "Entidade": [
                  {"GNR": "247"},
                  {"PSP": "162"}
                ]
              },
              {
                "Ano": "2011",
                "Entidade": [
                  {"GNR": "248"},
                  {"PSP": "181"}
                ]
              },
              {
                "Ano": "2012",
                "Entidade": [
                  {"GNR": "277"},
                  {"PSP": "150"}
                ]
              },
              {
                "Ano": "2013",
                "Entidade": [
                  {"GNR": "207"},
                  {"PSP": "169"}
                ]
              },
              {
                "Ano": "2014",
                "Entidade": [
                  {"GNR": "226"},
                  {"PSP": "137"}
                ]
              }
            ],
            "Distrito": "Évora",
            "Factor_amostra": 0.020521270111203194,
            "Somatorio_amostra": 2391
          },
          "VARNAME_1": null
        }
      },
      ...

и хотел бы получить доступ к свойству "dgai_violencia_domestica_2008_2014.Factor_amostra" каждого объекта, чтобы закодировать значение цвета.

Возможно ли это с помощью Leaflet+Omnivore или потребуется d3 или другая библиотека?

Текущая неработающая версия карты находится здесь с соответствующим кодом:

L.mapbox.accessToken = '...';
var map = L.mapbox.map('map', 'mapbox.streets').setView([39.5, -8.60], 7);

// Omnivore will AJAX-request this file behind the scenes and parse it:
// note that there are considerations:
// - The file must either be on the same domain as the page that requests it,
//   or both the server it is requested from and the user's browser must
//   support CORS.

// Internally this function uses the TopoJSON library to decode the given file
// into GeoJSON.

function getColor(d) {
    return d > 0.75 ? '#800026' :
           d > 0.50  ? '#FC4E2A' :
           d > 0.25   ? '#FD8D3C' :
                      '#FFEDA0';
}

var pt = omnivore.topojson('dgai_violencia_domestica_2008_2014.topo.json');

function style(geometry) {
  return {
    fillColor: getColor(geometry.properties.dgai_violencia_domestica_2008_2014.Peso_na_duracao_da_amostra),
    weight: 1,
    opacity: 1,
    color: 'white',
    dashArray: '3',
    fillOpacity: 1
};
}

pt.setStyle(style);
pt.addTo(map);

Толчок в правильном направлении, кто-нибудь?

Заранее спасибо.


person bcsantos    schedule 15.02.2016    source источник


Ответы (1)


Провел некоторое тестирование, и, как выяснилось, функция setStyle не будет выполняться:

pt.setStyle(function (feature) {
    console.log('Yay, i am executed!');
    return {
        'color': 'red'
    }
});

Использование этого Yay, i am executed! никогда не регистрируется в консоли. Это заставило меня заподозрить, что с setStyle методом Всеядного что-то не так. Итак, я попробовал это с пользовательским слоем:

var geojson = new L.GeoJSON(null);

var pt = omnivore.topojson(url, null, geojson).addTo(map);

geojson.setStyle(function (feature) {
    console.log('Yay, i am executed!');
    return {
        'color': 'red'
    };
});

То же самое, Yay, i am executed! никогда не заходит в консоль. Осталось попробовать вариант style для L.GeoJSON:

var geojson = new L.GeoJSON(null, {
    'style': function (feature) {
        console.log('Yay, i am executed!');
        return {
            'color': 'red'
        };
    }
});

var pt = omnivore.topojson(url, null, geojson).addTo(map);

И вот, это делает то, что он должен делать. Итак, я попробовал это с вашей функцией стиля и цвета и набором данных:

function getColor(d) {
    return d > 0.75 ? '#800026' :
           d > 0.50 ? '#FC4E2A' :
           d > 0.25 ? '#FD8D3C' :
                      '#FFEDA0';
}

function getStyle (feature) {
    return {
        fillColor: getColor(feature.properties.dgai_violencia_domestica_2008_2014.Peso_na_duracao_da_amostra),
        weight: 1,
        opacity: 1,
        color: 'white',
        dashArray: '3',
        fillOpacity: 1
    };
}

var geojson = new L.GeoJSON(null, {
    'style': getStyle
});

var pt = omnivore.topojson(url, null, geojson).addTo(map);

Это дает мне следующую ошибку:

Uncaught TypeError: невозможно прочитать свойство «Peso_na_duracao_da_amostra» неопределенного

Это потому, что в третьей функции это свойство отсутствует. Итак, ваш набор данных поврежден или неполный. Надеюсь, это поможет вам, удачи, вот плункер моего эксперимента, который работает (пока):

http://plnkr.co/edit/P6t96hTaOgSxTc4TPUuV?p=preview

person iH8    schedule 16.02.2016
comment
Это сделало это. Я написал скетч обработки, чтобы собрать все строки в исходном наборе данных, относящиеся к районам, в объекты json, а затем сопоставить их с именами в файле TopoJSON. в его нынешнем виде сопоставление имен недостаточно надежно. Спасибо. - person bcsantos; 16.02.2016
comment
Попробуйте использовать topojson.js, так как он преобразует GeometryCollection обратно в FeatureCollection, чтобы вы могли использовать ключи features.properties. Я не делал этого, так как в настоящее время пытаюсь понять это со своей стороны. - person redshift; 19.02.2016