231 lines
8.0 KiB
HTML
231 lines
8.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Mapbox GL JS + D3.js Integration</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<script src="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"></script>
|
|
<link href="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css" rel="stylesheet">
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
font-family: Arial, sans-serif;
|
|
}
|
|
#map {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 100%;
|
|
}
|
|
#info {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
background: white;
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
z-index: 1000;
|
|
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
|
}
|
|
#chart {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
width: 300px;
|
|
height: 200px;
|
|
background: white;
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
z-index: 1000;
|
|
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="map"></div>
|
|
<div id="info">
|
|
<h3>Mapbox + D3.js Demo</h3>
|
|
<p>Interactive map with D3 data visualization</p>
|
|
</div>
|
|
<div id="chart">
|
|
<h4>Population Distribution</h4>
|
|
<svg id="bar-chart" width="280" height="150"></svg>
|
|
</div>
|
|
|
|
<script>
|
|
// Initialize Mapbox GL JS
|
|
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9yZGl0b3N0IiwiYSI6ImQtcVkyclEifQ.vwKrOGZoZSj3N-9MB6FF_A'; // Replace with your token
|
|
|
|
const map = new mapboxgl.Map({
|
|
container: 'map',
|
|
style: 'mapbox://styles/mapbox/streets-v12',
|
|
center: [-100, 40],
|
|
zoom: 3
|
|
});
|
|
|
|
// Sample data - in real app this could come from an API or file
|
|
const sampleData = [
|
|
{ name: "New York", population: 8336817, coordinates: [-74.006, 40.7128] },
|
|
{ name: "Los Angeles", population: 3979576, coordinates: [-118.2437, 34.0522] },
|
|
{ name: "Chicago", population: 2746388, coordinates: [-87.6298, 41.8781] },
|
|
{ name: "Houston", population: 2320268, coordinates: [-95.3698, 29.7604] },
|
|
{ name: "Phoenix", population: 1680992, coordinates: [-112.0740, 33.4484] },
|
|
{ name: "Philadelphia", population: 1584064, coordinates: [-75.1652, 39.9526] }
|
|
];
|
|
|
|
// Use D3 to process and visualize data
|
|
const populationData = sampleData.map(d => d.population);
|
|
const maxPopulation = Math.max(...populationData);
|
|
|
|
// Create bar chart with D3
|
|
function createBarChart() {
|
|
const svg = d3.select("#bar-chart");
|
|
const width = +svg.attr("width");
|
|
const height = +svg.attr("height");
|
|
|
|
// Clear existing content
|
|
svg.selectAll("*").remove();
|
|
|
|
// Set up scales
|
|
const xScale = d3.scaleBand()
|
|
.domain(sampleData.map(d => d.name))
|
|
.range([0, width])
|
|
.padding(0.1);
|
|
|
|
const yScale = d3.scaleLinear()
|
|
.domain([0, maxPopulation])
|
|
.range([height, 0]);
|
|
|
|
// Create bars
|
|
svg.selectAll(".bar")
|
|
.data(sampleData)
|
|
.enter()
|
|
.append("rect")
|
|
.attr("class", "bar")
|
|
.attr("x", d => xScale(d.name))
|
|
.attr("width", xScale.bandwidth())
|
|
.attr("y", d => yScale(d.population))
|
|
.attr("height", d => height - yScale(d.population))
|
|
.attr("fill", "#3b82f6");
|
|
|
|
// Add value labels
|
|
svg.selectAll(".label")
|
|
.data(sampleData)
|
|
.enter()
|
|
.append("text")
|
|
.attr("class", "label")
|
|
.attr("x", d => xScale(d.name) + xScale.bandwidth() / 2)
|
|
.attr("y", d => yScale(d.population) - 5)
|
|
.attr("text-anchor", "middle")
|
|
.text(d => Math.round(d.population / 1000000) + "M");
|
|
}
|
|
|
|
// Create map markers with D3 processing
|
|
function createMarkers() {
|
|
const markers = [];
|
|
|
|
sampleData.forEach((city, index) => {
|
|
// Use D3 to process data for marker styling
|
|
const normalizedPopulation = city.population / maxPopulation;
|
|
|
|
// Create marker element
|
|
const el = document.createElement('div');
|
|
el.className = 'marker';
|
|
el.style.width = '20px';
|
|
el.style.height = '20px';
|
|
el.style.background = `rgba(59, 130, 246, ${normalizedPopulation})`;
|
|
el.style.borderRadius = '50%';
|
|
el.style.border = '2px solid white';
|
|
el.style.boxShadow = '0 0 5px rgba(0,0,0,0.5)';
|
|
|
|
// Add click interaction
|
|
el.addEventListener('click', () => {
|
|
alert(`${city.name}: ${city.population.toLocaleString()} people`);
|
|
});
|
|
|
|
// Create marker
|
|
const marker = new mapboxgl.Marker(el)
|
|
.setLngLat(city.coordinates)
|
|
.addTo(map);
|
|
|
|
markers.push(marker);
|
|
});
|
|
}
|
|
|
|
// Initialize everything when map is loaded
|
|
map.on('load', function () {
|
|
// Create D3 visualizations
|
|
createBarChart();
|
|
|
|
// Create map markers
|
|
createMarkers();
|
|
|
|
// Add a custom data layer using D3 processed data
|
|
const geojsonData = {
|
|
type: "FeatureCollection",
|
|
features: sampleData.map(city => ({
|
|
type: "Feature",
|
|
geometry: {
|
|
type: "Point",
|
|
coordinates: city.coordinates
|
|
},
|
|
properties: {
|
|
name: city.name,
|
|
population: city.population
|
|
}
|
|
}))
|
|
};
|
|
|
|
// Add source and layer for data visualization
|
|
map.addSource('cities', {
|
|
type: 'geojson',
|
|
data: geojsonData
|
|
});
|
|
|
|
map.addLayer({
|
|
id: 'cities-points',
|
|
type: 'circle',
|
|
source: 'cities',
|
|
paint: {
|
|
'circle-radius': [
|
|
'interpolate', ['linear'], ['get', 'population'],
|
|
1000000, 5,
|
|
8000000, 20
|
|
],
|
|
'circle-color': '#3b82f6',
|
|
'circle-stroke-width': 1,
|
|
'circle-stroke-color': '#ffffff'
|
|
}
|
|
});
|
|
|
|
// Add a simple legend using D3
|
|
const legendData = [
|
|
{ label: "Small", population: 1000000 },
|
|
{ label: "Medium", population: 4000000 },
|
|
{ label: "Large", population: 8000000 }
|
|
];
|
|
|
|
const legendSvg = d3.select("#info")
|
|
.append("div")
|
|
.attr("id", "legend")
|
|
.style("margin-top", "10px");
|
|
|
|
legendSvg.selectAll("circle")
|
|
.data(legendData)
|
|
.enter()
|
|
.append("circle")
|
|
.attr("r", d => Math.sqrt(d.population / 100000))
|
|
.attr("cx", (d, i) => i * 30 + 10)
|
|
.attr("cy", 20)
|
|
.attr("fill", "#3b82f6");
|
|
});
|
|
|
|
// Handle window resize
|
|
window.addEventListener('resize', function() {
|
|
map.resize();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |