Files
mcm-mfp/task1/fig1_carto.html
2026-01-19 19:43:57 +08:00

143 lines
4.6 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Task 1 Fig.1 (CartoDB + Leaflet)</title>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
crossorigin=""
/>
<style>
html,
body,
#map {
height: 100%;
margin: 0;
}
.legend {
background: rgba(255, 255, 255, 0.92);
padding: 10px 12px;
border-radius: 8px;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.15);
font: 12px/1.3 system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
}
.legend .title {
font-weight: 700;
margin-bottom: 6px;
}
.legend .row {
display: flex;
justify-content: space-between;
gap: 12px;
white-space: nowrap;
}
.legend .bar {
height: 10px;
border-radius: 6px;
margin-top: 6px;
/* warmer + more contrast */
background: linear-gradient(90deg, #fce8c8, #f4a261, #e76f51, #9b2226);
}
.legend .muted {
color: rgba(0, 0, 0, 0.65);
margin-top: 6px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
<script src="./fig1_points.js"></script>
<script>
const points = window.FIG1_POINTS || [];
if (!points.length) {
alert("FIG1_POINTS 为空:请确认 fig1_points.js 与本文件在同一目录。");
}
const map = L.map("map", { preferCanvas: true });
// CartoDB basemap (Positron)
L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", {
subdomains: "abcd",
maxZoom: 20,
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OSM</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
}).addTo(map);
const kValues = points.map((p) => p.k);
const muValues = points.map((p) => p.mu);
const kMin = Math.min(...kValues);
const kMax = Math.max(...kValues);
const muMin = Math.min(...muValues);
const muMax = Math.max(...muValues);
function clamp01(x) {
return Math.max(0, Math.min(1, x));
}
function lerp(a, b, t) {
return a + (b - a) * t;
}
function colorForK(k) {
const t = clamp01((k - kMin) / (kMax - kMin || 1));
// warm gradient: cream -> orange -> terracotta -> deep red
const stops = [
[252, 232, 200], // #fce8c8
[244, 162, 97], // #f4a261
[231, 111, 81], // #e76f51
[155, 34, 38], // #9b2226
];
const n = stops.length - 1;
const pos = t * n;
const idx = Math.min(n - 1, Math.floor(pos));
const tt = pos - idx;
const from = stops[idx];
const to = stops[idx + 1];
const r = Math.round(lerp(from[0], to[0], tt));
const g = Math.round(lerp(from[1], to[1], tt));
const bl = Math.round(lerp(from[2], to[2], tt));
return `rgb(${r},${g},${bl})`;
}
function radiusForMu(mu) {
const t = clamp01((mu - muMin) / (muMax - muMin || 1));
return lerp(5, 19, t);
}
const layer = L.featureGroup();
for (const p of points) {
const marker = L.circleMarker([p.lat, p.lng], {
radius: radiusForMu(p.mu),
color: "rgba(255,255,255,0.95)",
weight: 1.2,
fillColor: colorForK(p.k),
fillOpacity: 0.9,
});
marker.bindPopup(
`<div style="font: 13px/1.3 system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;">\n` +
`<div style="font-weight:700;margin-bottom:6px;">${p.site_id}. ${p.site_name}</div>` +
`<div><b>mu</b>: ${p.mu.toFixed(1)}</div>` +
`<div><b>k</b>: ${p.k}</div>` +
`</div>`
);
layer.addLayer(marker);
}
layer.addTo(map);
map.fitBounds(layer.getBounds().pad(0.12));
const legend = L.control({ position: "bottomleft" });
legend.onAdd = function () {
const div = L.DomUtil.create("div", "legend");
div.innerHTML =
`<div class="title">Task 1 Fig.1</div>` +
`<div class="row"><span>颜色: k</span><span>${kMin}${kMax}</span></div>` +
`<div class="bar"></div>` +
`<div class="muted">点大小: mu线性缩放</div>`;
return div;
};
legend.addTo(map);
</script>
</body>
</html>