Переключение видимости слоев на интерактивной карте


Я создаю интерактивные квада(тепла) на карте Геологической службы США четырехугольников где каждый квад имеет 12 различных атрибутов полей CSV-файл, прикрепленный к JSON с использованием papa.parse.

В настоящее время, я использую два различных переключателей для выбора значений, которые обновляют интерактивной веб-карте. Я планирую расширить значений, доступных для переключения (например, вместо животных, я буду иметь больше групп - рыб, птиц, рептилий и т. д. (т. е. каждый квад может иметь 40-50 полей атрибута)). Это увеличивает возможное количество перестановок (и я, наверное, переключиться с радио-кнопки, чтобы какой-то из выпадающего selector). Мой код в настоящее время имеет 12 условные операторы. Как я могу упростить этот код, так что, когда я добавить больше ценности и я не пишу еще на 30-40 if заявления?

  (function () {
  L.mapbox.accessToken =
    'pk.eyJ1IjoiaWFuaG9ybiIsImEiOiJjamRocmdseWUxMjJ0MnlwNDdiMDd5ZXZzIn0.jBWD0r86k4pBSymNrCKfzw';
  var map = L.mapbox.map('map', 'mapbox.pirates', {
    zoomSnap: .1,
    center: [37.6438332, -85.6487252],
    zoom: 7,
    minZoom: 1,
    maxZoom: 20,
    fillOpacity: 1
    //maxBounds: L.latLngBounds([], [])
  });


  var attributeValue = "allRecords";
  // AJAX request for GeoJSON data
  $.getJSON('data/kyQuads.json', function (quads) {

    //AJAX Request for parsing of CSV data
    Papa.parse("data/eoUnion.csv", {
      download: true,
      header: true,
      complete: function (data) {
        // data is accessible to us here
       //console.log('data: ', data);

        processData(quads, data)
        console.log(quads, data)
      }
    });


  }); // end of $.getJSON()

  function processData(quads, data) {
    //console.log(quads);
    //console.log(data);

    // loop through all the quads
    for (var i = 0; i < quads.features.length; i++) {
      var props = quads.features[i].properties;


      for (var j = 0; j < data.data.length; j++) {
        //console.log(typeof data.object[j]);
        if (props.quad24name === data.data[j].QUAD_NAME) {
          // reassign the variables
          quads.features[i].properties = data.data[j]

          break;

        }
      }
    }

    drawMap(quads);

  }

  function drawMap(data) {
    // create Leaflet object with geometry data and add to map
    var dataLayer = L.geoJson(data, {
      style: function (feature) {
        return {
          color: 'blue',
          weight: 1,
          fillOpacity: 1,
          fillColor: '#1f78b4'
        };
      }
    }).addTo(map);
    //first set the zoom/center to the dataLayer's extent
    map.fitBounds(dataLayer.getBounds());

    // call the update function
    updateMap(dataLayer);
    addUi(dataLayer);
    addLegend();
  } // end function drawMap
  function updateMap(dataLayer) {

    // reference to get sample jquery radio button: 
    // http: //www.jquerybyexample.net/2012/02/get-radio-button-value-using-jquery.html
    //jquery to select input values
    var presenceValue = $('input[name=toggle]:checked').val()
    var taxonomyValue = $('input[name=toggle2]:checked').val()

    //console.log(taxonomyValue, presenceValue)
    if (presenceValue === "allRecords" && taxonomyValue === "allRecords") {
      attributeValue = "allRecords"
    }
    if (presenceValue === "allRecords" && taxonomyValue === "Animals") {
      attributeValue = "Animals"
    }
    if (presenceValue === "allRecords" && taxonomyValue === "Plants") {
      attributeValue = "Plants"
    }
    if (presenceValue === "allRecords" && taxonomyValue === "Communities") {
      attributeValue = "Communities"
    }
    if (presenceValue === "Extant" && taxonomyValue === "allRecords") {
      attributeValue = "Extant"
    }
    if (presenceValue === "Extant" && taxonomyValue === "Animals") {
      attributeValue = "eAnimals"
    }
    if (presenceValue === "Extant" && taxonomyValue === "Plants") {
      attributeValue = "ePlants"
    }
    if (presenceValue === "Extant" && taxonomyValue === "Communities") {
      attributeValue = "eCommunities"
    }
    if (presenceValue === "Historic/Extirpated" && taxonomyValue === "allRecords") {
      attributeValue = "Historic/Extirpated"
    }
    if (presenceValue === "Historic/Extirpated" && taxonomyValue === "Animals") {
      attributeValue = "hAnimals"
    }
    if (presenceValue === "Historic/Extirpated" && taxonomyValue === "Plants") {
      attributeValue = "hPlants"
    }
    if (presenceValue === "Historic/Extirpated" && taxonomyValue === "Communities") {
      attributeValue = "hCommunities"
    }

    //console.log(attributeValue)
    // get the class breaks for the current data attribute
    var breaks = getClassBreaks(dataLayer);
    updateLegend(breaks);
    // loop through each county layer to update the color and tooltip info
    dataLayer.eachLayer(function (layer) {
      var props = layer.feature.properties;
      // set the fill color of layer based on its normalized data value
      if (+props[attributeValue] > 0) {
        // set the fill color of layer based on its normalized data value
        layer.setStyle({
          fillColor: getColor(+props[attributeValue], breaks),
          opacity: 1,
          fillOpacity: 1
        });
      } else {
        layer.setStyle({
          opacity: 0,
          fillOpacity: 0
        })
      }

      // assemble string sequence of info for tooltip (end line break with + operator)
      var tooltipInfo = "QUAD: " + props["quad24name"] + "<br>" + "# of Records" + ": " +
        props[attributeValue] + " EOs";
      // bind a tooltip to layer with county-specific information
      layer.bindTooltip(tooltipInfo, {
        // sticky property so tooltip follows the mouse
        sticky: true,
        tooltipAnchor: [300, 200]
      });
    });
  }

  function getClassBreaks(dataLayer) {
    // create empty Array for storing values
    var values = [];
    // loop through all the quads
    dataLayer.eachLayer(function (layer) {
      var value = layer.feature.properties[attributeValue];
      // don't push zero values into the array
      if (value > 0) {
        values.push(+value); // push the value for each layer into the Array
      }
    });
    // determine similar clusters
    var clusters = ss.ckmeans(values, 5);
    // create an array of the lowest value within each cluster
    var breaks = clusters.map(function (cluster) {
      return [cluster[0], cluster.pop()];
    });

    //return array of arrays, e.g., [[0,5], [6, 10], etc]
    return breaks;
  }

  function getColor(d, breaks) {
    // function accepts a single  data attribute value
    // and uses a series of conditional statements to determine which
    // which color value to return to return to the function caller
    // https://carto.com/carto-colors/
    // #c4e6c3,#96d2a4,#6dbc90,#4da284,#36877a,#266b6e,#1d4f60
    if (d <= breaks[0][1]) {
      return '#c4e6c3';
    } else if (d <= breaks[1][1]) {
      return '#96d2a4';
    } else if (d <= breaks[2][1]) {
      return '#6dbc90';
    } else if (d <= breaks[3][1]) {
      return '#36877a'
    } else if (d <= breaks[4][1]) {
      return '#1d4f60'
    }
  }

  function addLegend(breaks) {
    // create a new Leaflet control object, and position it top left
    var legendControl = L.control({
      position: 'topleft'
    });
    // when the legend is added to the map
    legendControl.onAdd = function (map) {
      // select a div element with an id attribute of legend
      var legend = L.DomUtil.get('legend');
      // disable scroll and click/touch on map when on legend
      L.DomEvent.disableScrollPropagation(legend);
      L.DomEvent.disableClickPropagation(legend);
      // return the selection to the method
      return legend;
    };
    // add the empty legend div to the map
    legendControl.addTo(map);
  }

  function updateLegend(breaks) {
    // get the currently selected values 
    // var taxonomyValue = $("#taxonomy-selector option:selected").val()
    var taxonomyValue = $('input[name=toggle2]:checked').val()

    var presenceValue = $('input[name=toggle]:checked').val()

    //  if/else statement to change title

    if (taxonomyValue == "allRecords") {
      taxonomyValue = "EOs"
    }

    if (presenceValue == "allRecords") {
      presenceValue = "All"
    }

    //  console.log(taxonomyValue, presenceValue);

    // select the legend, add a title, begin an unordered list and assign to a variable
    var legend = $('#legend').html("<h5>" + presenceValue + " " + taxonomyValue + " </h5>");
    // loop through the Array of classification break values
    for (var i = 0; i <= breaks.length - 1; i++) {
      var color = getColor(breaks[i][0], breaks);
      legend.append('<span style="background:' + color + '"></span> ' +
        '<label>' + (breaks[i][0]) + ' &mdash; ' + (breaks[i][1]) +
        '</label>');
    }
  }

  function addUi(dataLayer) {
    // create the slider control
    var selectControl = L.control({
      position: 'topright'
    });
    // when control is added
    selectControl.onAdd = function (map) {
      // get the element with id attribute of ui-controls
      return L.DomUtil.get("ui-presence");
    }
    // add the control to the map
    selectControl.addTo(map);
    $('input[name="toggle"]').change(function () {
      // call updateMap function
      updateMap(dataLayer);
    });

    // create the slider control
    var selectControl = L.control({
      position: 'topright'
    });
    // when control is added
    selectControl.onAdd = function (map) {
      // get the element with id attribute of ui-controls
      return L.DomUtil.get("ui-controls");
    }
    // add the control to the map
    selectControl.addTo(map);
    $('input[name=toggle2]').change(function () {
      // call updateMap function
      updateMap(dataLayer);
    });

  }

})()

Значение, присвоенное attributeValue ссылается на атрибут таблицы, прикрепленный к моей JSON-данных.

enter image description here

Как мне переключаться между различными радио-кнопки, attributeValue изменения в соответствующее значение в таблице.



165
0
задан 2 апреля 2018 в 05:04 Источник Поделиться
Комментарии
2 ответа

Вариант 1

Предложили только на будущее

// Don't repeat the same check
// Chain them if they are mutually exclusive
if (presenceValue === "allRecords") {
if (taxonomyValue === "allRecords") {
attributeValue = "allRecords"
} else if (taxonomyValue === "Animals") {
attributeValue = "Animals"
} else if (taxonomyValue === "Plants") {
attributeValue = "Plants"
} else if (taxonomyValue === "Communities") {
attributeValue = "Communities"
}
} else if (presenceValue === "Extant") {
if (taxonomyValue === "allRecords") {
attributeValue = "Extant"
} else if (taxonomyValue === "Animals") {
attributeValue = "eAnimals"
} else if (taxonomyValue === "Plants") {
attributeValue = "ePlants"
} else if (taxonomyValue === "Communities") {
attributeValue = "eCommunities"
}
} else if (presenceValue === "Historic/Extirpated") {
if (taxonomyValue === "allRecords") {
attributeValue = "Historic/Extirpated"
} else if (taxonomyValue === "Animals") {
attributeValue = "hAnimals"
} else if (taxonomyValue === "Plants") {
attributeValue = "hPlants"
} else if (taxonomyValue === "Communities") {
attributeValue = "hCommunities"
}
}

Вариант 2

Использовать alghoritm/формулу, чтобы создать имя attributeValue от presenceValue & taxonomyValue.

var presenceValueOptions = {
"allRecords": "all",
"Extant": "ext",
"Historic/Extirpated": "his"
}
var taxonomyValueOptions = {
"allRecords": "all",
"Animals": "Animals",
"Plants": "Plants",
"Communities": "Comunities"

}
var presenceValue = $("input[name=toggle]:checked").val()
var taxonomyValue = $("input[name=toggle2]:checked").val()

attributeValue = presenceValueOptions[presenceValue] + taxonomyValueOptions[taxonomyValue]

Этот выходы:

"allRecords" && "allRecords" -> attributeValue = "allall"
"allRecords" && "Animals" -> attributeValue = "allAnimals"
...
"Extant" && "Animals" -> attributeValue = "extAnimals"
"Extant" && "Plants" -> attributeValue = "extPlants"

Вы можете добавить таксономию, просто добавив свойство taxonomyValueOptions.


Ответ на ваш комментарий относительно поля переименовать

Внутри presenceValueOptions & taxonomyValueOptions:

propertyName должен соответствовать вашему радио кнопки значение;

propertyValue может быть все, что угодно, покуда, в конце концов, оно совпадает с вашим полей.

Вы можете установить presenceValueOptions.allRecords для "allP" и taxonomyValueOptions.allRecords для "allT" который является более выразительным.

1
ответ дан 3 апреля 2018 в 03:04 Источник Поделиться


Как я могу упростить этот код, так что, когда я добавить больше ценности и я не пишу еще на 30-40 if заявления?

Можно определить отображение (похож на второй вариант В Валентин ответ), которая похожа на 2-мерный массив. Это может быть достигнуто в JavaScript с помощью объектов- при необходимости с помощью карты объекта.

var mapping = { //format: presenceValue: { taxonomyValue: attributeValue }
"allRecords": {
"allRecords": "allRecords",
"Animals": "Animals",
"Plants": "Plants",
"Communities": "Communities"
},
"Extant": {
"allRecords": "Extant",
"Animals": "eAnimals",
"Plants": "ePlants",
"Communities": "eCommunities"
},
"Historic/Extirpated": {
"allRecords": "Historic/Extirpated",
"Animals": "hAnimals",
"Plants": "hPlants",
"Communities": "hCommunities"
}
};

Затем просто присвоить значение из этого сопоставления с использованием скобок сопоставления объекта:

var attributeValue = mapping[presenceValue][taxonomyValue];

Если кто-то хочет, чтобы убедиться, что attributeValue бы вам назначить undefinedвы могли бы проверить, если ключи существуют, используя объект.метод hasOwnProperty() :

if (mapping.hasOwnProperty(presenceValue) && mapping[presenceValue].hasOwnProperty(taxonomyValue)) {
var attributeValue = mapping[presenceValue][taxonomyValue];
//rest of code to utilize that value
}

иначе in оператор

if (presenceValue in mapping && taxonomyValue in mapping[presenceValue]) {
var attributeValue = mapping[presenceValue][taxonomyValue];
//rest of code to utilize that value
}

Что декларация mapping может храниться вне updateMap() функция, возможно, во внешней JSON-файла.

Вы могли бы также рассмотреть использование карты вместо обычного объекта.

Других точек обзора

Множественные библиотеки jQuery загружается

Я заметил, что связанный карте страница включает в себя две версии jQuery (т. е. 3.3.1 и 3.2.1). А эти двое, вероятно, не будет иметь каких-либо противоречивых код, в том числе библиотека дважды бессмысленно, и в то время как большинство кэша браузера, это приводит к дополнительному 34.6 КБ, что пользователь должен скачать.

Вы могли бы рассмотреть, действительно ли вы необходим jQuery... проверить youmightnotneedjquery.com/ альтернативы. На странице уже есть 6 другие скрипты включены...

Я проверил страницу через плагин Yslow - дал ему б оценка:

1

Хранить ссылки дом в переменной (или константе)

В updateMap() функция делает дом поиск, чтобы получить значение радио кнопки при каждом вызове. Те дом ссылки должны храниться в переменной (или константе , если в браузерах, которые поддерживают const достаточно). Я знаю, вы говорили, что рассматривают возможность перехода на использование списков выбора, поэтому я предлагаю просто хранить ссылки на эти купить код значения атрибута в функцию, когда дом готов (например, в jQuery .готов()).

Избежать дополнительных анонимной функции

Я вижу пару мест, где обработчики изменить настройки, как показано ниже:


$('input[name="toggle"]').change(function () {
// call updateMap function
updateMap(dataLayer);
});
//....
$('input[name=toggle2]').change(function () {
// call updateMap function
updateMap(dataLayer);
});

Это могут быть упрощены, используя функцию.привязать() , чтобы удалить лишние упаковки функция:

$('input[name="toggle"], input[name=toggle2]').change(updateMap.bind(null, dataLayer));

Обратите внимание, что CSS-селекторы были объединены с запятой. Имя класса или другой метод может быть использован для выбора этих элементов.

Подробнее об удалении лишних анонимные функции в этой статье

0
ответ дан 3 апреля 2018 в 07:04 Источник Поделиться