我可以初始化地图并添加 geojson 多边形。但我无法根据所选选项更新不透明度。我能够检索这些值并计算每个邮政编码的标准化值,但我无法获得反映新值的不透明度。
一切都会返回更新后的 geojson,其中包含基于选择的值。但我无法使用新的不透明度级别更新图层。
我在控制台日志中收到此错误:
(index):181错误:TypeError:map.setPaintProperty不是函数 在(索引):259:21 在Array.forEach() 在 updateMap ((index):216:34) 在(索引):173:17
fetch('https://vizibalmaps.s3.amazonaws.com/2023_zipcode_20mb.json')
.then(response => response.json())
.then(data => {
// Initialize the map
console.log('GeoJSON Data:', data);
console.log('GeoJSON Zipcode Type:', typeof data.features[0].properties.ZCTA5CE20);
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-74.5, 40], // Default center coordinates
zoom: 4, // Adjust the zoom level
});
// Store the fetched data in the global variable
geojsonData = data;
map.on('load', function () {
map.addSource('polygons', {
type: 'geojson',
data: geojsonData, // Use the global variable to set the data
});
map.addLayer({
id: 'polygons',
type: 'fill',
source: 'polygons',
paint: {
'fill-color': '#FF5733',
// 'fill-opacity': 0.3,
'fill-outline-color': '#088',
},
});
.catch(error => console.error('Error fetching GeoJSON:', error));
// Function to update the map based on new data
function normalize(value, min, max) {
// Map the value from the range [min, max] to [0, 1]
return (value - min) / (max - min);
}
function getValueFromData(outputData, zipcode) {
// Find the entry with the matching zipcode
var entry = outputData.find(entry => entry.zipcode === zipcode);
// Return the output_value if the entry is found, otherwise return null or handle appropriately
return entry ? parseInt(entry.output_value) : null;
}
function updateMap(data) {
// Log the data to the console to examine its structure
// console.log(data);
// Extract the output data
var outputData = data.output;
// Get the min and max values from the data
var values = outputData.map(entry => parseInt(entry.output_value));
var minValue = Math.min(...values);
var maxValue = Math.max(...values);
// Iterate over the GeoJSON features to calculate normalized opacity based on the value
geojsonData.features.forEach(feature => {
// Check if the zipcode property exists in feature.properties
if (feature.properties.hasOwnProperty('ZCTA5CE20')) {
// console.log('GeoJSON Zipcode:', feature.properties.ZCTA5CE20); // check geojson zipcode format
// console.log('GeoJSON Zipcode Type:', typeof geojsonData.features[0].properties.ZCTA5CE20);
var zipcode = feature.properties.ZCTA5CE20;
var value = getValueFromData(outputData, zipcode); // Assuming you have a function to extract the value from the data
// console.log('var Zipcode:', zipcode); // check geojson zipcode format
// console.log('outputData value:', value);
// Check if a value was found for the zipcode
if (value !== null) {
var normalizedValue = normalize(value, minValue, maxValue);
var opacity = normalizedValue;
console.log(`Zipcode: ${zipcode}, Output Value: ${value}, normalizedValue: ${normalizedValue}`); // Log the zipcode and corresponding output value
feature.properties.opacity = opacity;
// Log the variables to the console
console.log("Zipcode:", zipcode);
console.log("Value:", value);
console.log("Normalized Value:", normalizedValue);
console.log("Opacity:", opacity);
} else {
console.log(`No output value found for zipcode: ${zipcode}`);
}
} else {
console.log('Zipcode property not found for feature:', feature);
}
// Optionally, you can set other properties such as color based on the opacity value
// Update the 'fill-opacity' property of the feature in the map layer
map.setPaintProperty('polygons', 'fill-opacity', opacity);
});
// Log the map object to the console
console.log(map);
// Update the data source for the 'polygons' layer
// map.getSource('polygons').setData(geojsonData);
}
</script>
</body>
</html>
我能够解决它。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Web App</title>
<!-- Include Mapbox GL CSS and JS -->
<link href="https://api.mapbox.com/mapbox-gl-js/v3.2.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.2.0/mapbox-gl.js"></script>
<!-- Your custom styles -->
<style>
#map {
height: 100vh;
width: 100%;
}
</style>
</head>
<body>
<form action="/" method="post" id="inputForm">
<label for="output">Output Metric:</label>
<select name="output_metric_value" id="output">
<option value="Housing Units">Housing Units</option>
<option value="Tenure" selected>Tenure</option>
</select>
<label for="race">Race:</label>
<select name="race_search_value" id="race">
<option value="All" selected>All</option>
<option value="White">White</option>
<option value="Black or African American">Black or African American</option>
<option value="American Indian and Alaskan Native">American Indian and Alaskan Native</option>
<option value="Asian">Asian</option>
<option value="Native Hawaiian and Other Pacific Islander">Native Hawaiian and Other Pacific Islander</option>
<option value="Other Race">Other Race</option>
<option value="2+ Races">2+ Races</option>
</select>
<label for="age">Age:</label>
<select name="age_search_value" id="age">
<option value="All" selected>All</option>
<option value="15 to 24 Years Old">15 to 24 Years Old</option>
<option value="25 to 34 Years Old">25 to 34 Years Old</option>
<option value="35 to 44 Years Old">35 to 44 Years Old</option>
<option value="45 to 54 Years Old">45 to 54 Years Old</option>
<option value="55 to 59 Years Old">55 to 59 Years Old</option>
<option value="60 to 64 Years Old">60 to 64 Years Old</option>
<option value="65 to 74 Years Old">65 to 74 Years Old</option>
<option value="75 to 84 Years Old">75 to 84 Years Old</option>
<option value="85+ Years Old">85+ Years Old</option>
</select>
<label for="marital_status">Marital Status:</label>
<select name="marital_status_value" id="marital_status">
<option value="All" selected>All</option>
<option value="Married Couple">Married Couple</option>
<option value="No Spouse Present">No Spouse Present</option>
<option value="No Spouse Present, Male Householder">No Spouse Present, Male Householder</option>
<option value="No Spouse Present, Female Householder">No Spouse Present, Female Householder</option>
<option value="Single">Single</option>
<option value="Single, Male Householder">Single, Male Householder</option>
<option value="Single, Female Householder">Single, Female Householder</option>
</select>
<label for="home_ownership">Home Ownership:</label>
<select name="home_ownership_value" id="home_ownership">
<option value="All" selected>All</option>
<option value="Owner Occupied">Owner Occupied</option>
<option value="Renter Occupied">Renter Occupied</option>
</select>
<input type="button" value="Submit" onclick="submitForm()">
</form>
<div id="map"></div>
<script>
// Your Mapbox access token
mapboxgl.accessToken = 'pk.eyJ1IjoidG1jYmV0aDgwIiwiYSI6ImNsdDZndW1rZTBhemIycm9lZWo0eXBlcXQifQ.Fphu4YiYP2eEsky0WIjyuQ';
var geojsonData;
var map;
// Fetch the GeoJSON data once when the page loads
fetch('https://vizibalmaps.s3.amazonaws.com/2023_zipcode_20mb.json')
.then(response => response.json())
.then(data => {
// Store the fetched data in the global variable
geojsonData = data;
// Initialize the map
map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-74.5, 40], // Default center coordinates
zoom: 4, // Adjust the zoom level
});
map.on('load', function () {
// Add initial layer
addLayer('polygons', {
'fill-color': '#FF5733',
'fill-opacity': 0.3,
'fill-outline-color': '#088',
});
});
})
.catch(error => console.error('Error fetching GeoJSON:', error));
// Function to submit the form
function submitForm() {
// Get selected values from dropdowns
var outputMetric = document.getElementById('output').value;
var race = document.getElementById('race').value;
var age = document.getElementById('age').value;
var maritalStatus = document.getElementById('marital_status').value;
var homeOwnership = document.getElementById('home_ownership').value;
// Make an AJAX request to the server to get updated data
fetch('/process_data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
output_metric_value: outputMetric,
race_search_value: race,
age_search_value: age,
marital_status_value: maritalStatus,
home_ownership_value: homeOwnership,
}),
})
.then(response => response.json())
.then(data => {
// Log the data to the console to see its structure
console.log('Output Data:', data);
// Update the map with the new data and get the updated GeoJSON data
var updatedGeoJSON = updateMap(data);
// Log the updatedGeoJSON variable to the console
console.log('Updated GeoJSON:', updatedGeoJSON);
// Remove the existing layer
if (map.getLayer('polygons')) {
map.removeLayer('polygons');
}
// Add a new layer to the map with the updated GeoJSON data
map.addLayer({
id: 'updated-polygons',
type: 'fill',
source: {
type: 'geojson',
data: updatedGeoJSON,
},
paint: {
'fill-color': '#FF5733',
'fill-opacity': ['get', 'opacity'], // Use data-driven styling to set opacity
'fill-outline-color': '#088',
},
});
})
.catch(error => console.error('Error:', error));
}
function getValueFromData(outputData, zipcode) {
// Find the entry with the matching zipcode
var entry = outputData.find(entry => entry.zipcode === zipcode);
// Return the output_value if the entry is found, otherwise return null or handle appropriately
return entry ? parseInt(entry.output_value) : null;
}
function normalize(value, min, max) {
// Map the value from the range [min, max] to [0, 1]
return (value - min) / (max - min);
}
// Function to update the map based on new data
function updateMap(data) {
// Extract the output data
var outputData = data.output;
// Get the min and max values from the data
var values = outputData.map(entry => parseInt(entry.output_value));
var minValue = Math.min(...values);
var maxValue = Math.max(...values);
// Iterate over the GeoJSON features to calculate normalized opacity based on the value
geojsonData.features.forEach(feature => {
// Check if the zipcode property exists in feature.properties
if (feature.properties.hasOwnProperty('ZCTA5CE20')) {
var zipcode = feature.properties.ZCTA5CE20;
var value = getValueFromData(outputData, zipcode); // Assuming you have a function to extract the value from the data
// Check if a value was found for the zipcode
if (value !== null) {
var normalizedValue = normalize(value, minValue, maxValue);
var opacity = normalizedValue;
// Update the opacity value in the GeoJSON data
feature.properties.opacity = opacity;
} else {
console.log(`No output value found for zipcode: ${zipcode}`);
}
} else {
console.log('Zipcode property not found for feature:', feature);
}
});
return geojsonData;
// Log the updatedGeoJSON variable to the console
console.log('Updated GeoJSON:', geojsonData);
}
// Function to add a layer to the map
function addLayer(sourceId, paint) {
map.addSource(sourceId, {
type: 'geojson',
data: geojsonData,
});
map.addLayer({
id: sourceId,
type: 'fill',
source: sourceId,
paint: paint,
});
}
</script>
</body>
</html>