const aufgabe3 = async () => { const wantedYears = [2015, 2016, 2017] const wantedSeries = [ {code: "SH_H2O_SAFE", displayName: "drinking water"}, {code: "SH_SAN_SAFE", displayName: "sanitation"} ] const levels = [0, 50.0, 80.0, 85.0, 90.0, 95.0, 99.0, 99.9] const loadData = async () => { const loadSeries = async series => { let maxNumberOfElements = (await axios.get("https://unstats.un.org/SDGAPI/v1/sdg/Series/Data", { params: {seriesCode: series.code} } )).data.totalElements let requests = wantedYears.map(year => { return axios.get("https://unstats.un.org/SDGAPI/v1/sdg/Series/Data", { params: { seriesCode: series.code, pageSize: maxNumberOfElements, timePeriod: year } }) }) let dataArrays = (await Promise.all(requests)).map(arr => arr.data.data) const values = [].concat(...dataArrays) return values.filter(elem => elem.dimensions.Location === "ALLAREA") } const apiData = await Promise.all(wantedSeries.map(loadSeries)) return [].concat(...apiData) } const getColor = percentage => { switch (true) { case percentage > levels[7]: return '#00FF00' case percentage > levels[6]: return '#33CC00' case percentage > levels[5]: return '#4DB300' case percentage > levels[4]: return '#808000' case percentage > levels[3]: return '#996600' case percentage > levels[2]: return '#B34D00' case percentage > levels[1]: return '#CC3300' case percentage > levels[0]: return '#FF0000' } } const map = L.map('suiMap', {zoomControl: false}).setView([53.0, 14.0], 4) map.addLayer(new L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data OpenStreetMap contributors', minZoom: 0, maxZoom: 18 })) const [geojsonData, apiData] = await Promise.all([ $.getJSON('europe.geo.json'), loadData() ]) // Attach api data to geojson for (let elem of apiData) { const geoJsonFeature = geojsonData.features.find(value => { return value.properties.name_long.includes(elem.geoAreaName) || elem.geoAreaName.includes(value.properties.name_long) }) if (geoJsonFeature) geoJsonFeature.properties[elem.series + "_" + elem.timePeriodStart] = elem } // Add the legend to the map const legend = L.control({position: 'bottomright'}) legend.onAdd = () => { const legend = L.DomUtil.create('div', 'info legend') const labels = [] for (let i = 0; i < levels.length; i++) { labels.push( ' ' + levels[i].toFixed(1) + (levels[i + 1] ? '–' + levels[i + 1].toFixed(1) : '+') ) } legend.innerHTML = labels.join('
') return legend } legend.addTo(map) // Control that shows state info on hover const info = L.control({position: 'topleft'}) info.onAdd = () => { info._div = L.DomUtil.create('div', 'info') info.update() return info._div } info.update = (props = {}, currSeries) => { const localProps = props[currSeries] info._div.innerHTML = localProps ? `
${localProps.seriesDescription}
` : '' if (localProps) { let formattedPercentage = new Intl.NumberFormat('de-DE').format(localProps.value) info._div.innerHTML += `${props.formal_en}
${formattedPercentage} %` } else { info._div.innerHTML += 'Hover over a country' } } info.addTo(map) // Create datalayer instances for series and year let layers = {} for (let currSeries of wantedSeries) { for (let currYear of wantedYears) { let fullSeriesName = `${currSeries.code}_${currYear}` let geoJsonLayer = L.geoJson(geojsonData, { style: feature => ({ stroke: true, fill: true, fillColor: getColor(feature.properties[fullSeriesName].value), fillOpacity: 1, dashArray: '3', weight: 2, color: 'black' }), filter: feature => { return feature.properties.hasOwnProperty(fullSeriesName) }, onEachFeature: (feature, layer) => { layer.on({ mouseover: event => { event.target.setStyle({ weight: 5, color: '#666', dashArray: '', fillOpacity: 0.7 }) if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) event.target.bringToFront() info.update(feature.properties, fullSeriesName) }, mouseout: event => { geoJsonLayer.resetStyle(event.target) info.update() }, click: event => map.fitBounds(event.target.getBounds()) }) } }) layers[`${currSeries.code}_${currYear}`] = geoJsonLayer } } // Create button layer selector const layerSelector = L.control({position: "topright"}) layerSelector._div = L.DomUtil.create("div", "info text-center") layerSelector._div.id = "layerSelector" layerSelector.onAdd = () => { const createButtonGroup = (values, groupName) => { let outer = `
` for (let elem of values) { outer += ` ` } outer += `
` return outer } let seriesDiv = createButtonGroup(wantedSeries.map(ele => ({value: ele.code, name: ele.displayName})), "series") let yearDiv = createButtonGroup(wantedYears.map(ele => ({value: ele, name: ele})), "year") layerSelector._div.innerHTML = [seriesDiv, yearDiv].join("
") return layerSelector._div } layerSelector.addTo(map) // Create layerGroup for data layer (to keep the base osm layer when changing the data layer) const dataLayerGroup = L.layerGroup().addTo(map) $("#layerSelector input:radio").change(() => { let selectedSeries = $("#layerSelector input:radio[name='series']:checked")[0]?.value let selectedYear = $("#layerSelector input:radio[name='year']:checked")[0]?.value if (selectedSeries && selectedYear) { dataLayerGroup.clearLayers() dataLayerGroup.addLayer(layers[selectedSeries + "_" + selectedYear]) } }) } aufgabe3()