2026-06-08 00:53:55 +08:00

85 lines
2.7 KiB
JavaScript

import { formatMoney } from "../../utils/format.js";
export function createGeoOption(items) {
const points = items
.filter((item) => Array.isArray(item.geo_point) && item.geo_point.length === 2)
.filter((item) => Number(item.recharge_usd_minor) > 0)
.map((item) => [...item.geo_point, Number(item.recharge_usd_minor) || 0, item.country]);
const max = Math.max(...points.map((item) => item[2]), 1);
const min = Math.min(...points.map((item) => item[2]), max);
return {
animationDuration: 650,
geo: {
center: [38, 12],
emphasis: { disabled: true },
itemStyle: {
areaColor: "#18354e",
borderColor: "rgba(62, 139, 184, 0.52)",
borderWidth: 0.65
},
label: { show: false },
layoutCenter: ["50%", "51%"],
layoutSize: "112%",
map: "databi-world",
roam: false,
silent: true,
zoom: 1.04
},
series: [
{
coordinateSystem: "geo",
data: points,
itemStyle: {
color: ({ value }) => colorByValue(value[2], min, max, 0.2),
shadowBlur: 28,
shadowColor: "rgba(39, 228, 245, 0.6)"
},
silent: true,
symbolSize: (value) => 14 + (value[2] / max) * 32,
type: "scatter",
z: 2
},
{
coordinateSystem: "geo",
data: points,
itemStyle: {
borderColor: "rgba(232, 255, 255, 0.9)",
borderWidth: 1.5,
color: ({ value }) => colorByValue(value[2], min, max, 1),
shadowBlur: 24,
shadowColor: "rgba(39, 228, 245, 0.74)"
},
rippleEffect: { brushType: "stroke", number: 3, scale: 3.6 },
symbolSize: (value) => 6 + (value[2] / max) * 15,
type: "effectScatter",
z: 3
}
],
tooltip: {
backgroundColor: "#08243a",
borderColor: "#1a5f82",
formatter: ({ value }) => `${value[3]}<br/>${formatMoney(value[2])}`,
textStyle: { color: "#e9f6ff" }
}
};
}
function colorByValue(value, min, max, alpha = 1) {
const strength = normalizeStrength(value, min, max);
const low = [66, 129, 255];
const mid = [39, 228, 245];
const high = [36, 215, 159];
const from = strength < 0.55 ? low : mid;
const to = strength < 0.55 ? mid : high;
const local = strength < 0.55 ? strength / 0.55 : (strength - 0.55) / 0.45;
const [red, green, blue] = from.map((channel, index) => Math.round(channel + (to[index] - channel) * local));
return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
}
function normalizeStrength(value, min, max) {
if (max <= min) {
return 1;
}
return Math.min(Math.max((Math.sqrt(value) - Math.sqrt(min)) / (Math.sqrt(max) - Math.sqrt(min)), 0), 1);
}