千千块模板 | 全国各省市旅游足迹地图点亮模版
国庆节到了,看见论坛没有一个完美的旅游足迹,于是自己做了一个。
可以点击全国各省市的旅游足迹,并且可以自定义设置,数据会自动保存
功能
1.可以设置点亮每个地方都足迹
2.可以支持拉伸地图大小
3.可以自定义配色设置
4.数据会自动保存
将 map 文件夹放到 笔记工作区\data\assets
链接:https://pan.quark.cn/s/54825f81b15a
因为思源笔记机制,需要先做文档下面随便建一个 /chart 图表,然后就可以在上面的普通块使用了



RGB 在线网站:https://tools.jb51.net/static/colorpicker/
自定义块 css
/* @webpack */
.qianqian-map-block{min-height:200px;width:100%;position:relative;overflow:hidden;border:1px solid #dcdfe6;border-radius:4px}.qianqian-map-block .map-container{width:100%;height:100%;cursor:grab;user-select:none}.qianqian-map-block .map-container:active{cursor:grabbing}.qianqian-map-block .map-selector{position:absolute;top:10px;left:10px;z-index:10;cursor:pointer}.qianqian-map-block .back-button{padding:4px 8px;border-radius:4px;border:1px solid #ccc;background-color:#f0f0f0;cursor:pointer}.qianqian-map-block .back-button:hover{background-color:#e0e0e0}.qianqian-map-block .settings-panel{padding:20px;box-sizing:border-box}.qianqian-map-block .settings-panel .color-input-group{display:flex;align-items:center;justify-content:center;margin-bottom:10px}.qianqian-map-block .settings-panel .color-input-group label{margin-right:15px;font-weight:500;white-space:nowrap}.qianqian-map-block .settings-panel .color-input-group div{display:inline-flex;align-items:center}.qianqian-map-block .settings-panel .color-input-group input[type=number]{width:70px;padding:6px;font-size:1em;margin:0 8px 0 4px;text-align:center;border:1px solid #ccc;border-radius:4px}.qianqian-map-block .settings-panel button{margin-top:20px;padding:8px 16px;border-radius:4px;border:1px solid #ccc;background-color:#4477cb;color:#fff;cursor:pointer}.qianqian-map-block .settings-panel button:hover{background-color:#3a68b4}.qianqian-map-block .error-msg{display:flex;justify-content:center;align-items:center;height:100%;color:#f56c6c}
自定义块 js
/******/ "use strict";
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function initializeApp(blockElement, echarts) {
const blockId = blockElement.dataset.nodeId;
let mapHeight = 600;
const colors = {
background: "rgb(255, 255, 255)",
areaColor: "rgb(231, 232, 234)",
litColor: "rgb(244, 208, 63)"
};
const registeredMapsCache = /* @__PURE__ */ new Map();
const litRegionsSet = /* @__PURE__ */ new Set();
const litProvincesSet = /* @__PURE__ */ new Set();
let currentMapPath = "js/china";
function loadAndRegisterMap(mapPathFragment) {
return __async(this, null, function* () {
if (registeredMapsCache.has(mapPathFragment)) {
const cachedName = registeredMapsCache.get(mapPathFragment);
return Promise.resolve(cachedName);
}
const scriptSrc = `/assets/map/${mapPathFragment}.js?v=${Date.now()}`;
const originalRegisterMap = echarts.registerMap;
let capturedName = null;
return new Promise((resolve, reject) => {
echarts.registerMap = (name, data) => {
originalRegisterMap.call(echarts, name, data);
if (echarts.getMap(name)) {
capturedName = name;
}
};
const script = document.createElement("script");
script.src = scriptSrc;
script.onload = () => {
echarts.registerMap = originalRegisterMap;
if (capturedName) {
registeredMapsCache.set(mapPathFragment, capturedName);
resolve(capturedName);
} else {
const mapNameFromFile = mapPathFragment.split("/").pop();
reject(new Error(`\u672A\u80FD\u6355\u83B7\u5730\u56FE [${mapNameFromFile}] \u7684\u6CE8\u518C\u3002`));
}
};
script.onerror = () => {
echarts.registerMap = originalRegisterMap;
reject(new Error(`\u52A0\u8F7D\u5730\u56FE\u811A\u672C [${scriptSrc}] \u5931\u8D25\u3002`));
};
document.head.appendChild(script);
});
});
}
blockElement.innerHTML = "";
blockElement.className = "qianqian-map-block";
blockElement.style.position = "relative";
const container = document.createElement("div");
container.className = "map-container";
const selector = document.createElement("select");
selector.className = "map-selector";
const backButton = document.createElement("button");
backButton.className = "back-button";
backButton.textContent = "\u8FD4\u56DE";
backButton.style.display = "none";
backButton.style.position = "absolute";
backButton.style.top = "10px";
backButton.style.right = "10px";
backButton.style.zIndex = "10";
const settingsPanel = document.createElement("div");
settingsPanel.className = "settings-panel";
settingsPanel.style.display = "none";
blockElement.append(selector, backButton, container, settingsPanel);
const mapOptions = {
"\u4E2D\u56FD": "js/china",
"\u8BBE\u7F6E": "special/settings",
"\u5B89\u5FBD": "js/province/anhui",
"\u6FB3\u95E8": "js/province/aomen",
"\u5317\u4EAC": "js/province/beijing",
"\u91CD\u5E86": "js/province/chongqing",
"\u798F\u5EFA": "js/province/fujian",
"\u7518\u8083": "js/province/gansu",
"\u5E7F\u4E1C": "js/province/guangdong",
"\u5E7F\u897F": "js/province/guangxi",
"\u8D35\u5DDE": "js/province/guizhou",
"\u6D77\u5357": "js/province/hainan",
"\u6CB3\u5317": "js/province/hebei",
"\u9ED1\u9F99\u6C5F": "js/province/heilongjiang",
"\u6CB3\u5357": "js/province/henan",
"\u6E56\u5317": "js/province/hubei",
"\u6E56\u5357": "js/province/hunan",
"\u6C5F\u82CF": "js/province/jiangsu",
"\u6C5F\u897F": "js/province/jiangxi",
"\u5409\u6797": "js/province/jilin",
"\u8FBD\u5B81": "js/province/liaoning",
"\u5185\u8499\u53E4": "js/province/neimenggu",
"\u5B81\u590F": "js/province/ningxia",
"\u9752\u6D77": "js/province/qinghai",
"\u5C71\u4E1C": "js/province/shandong",
"\u4E0A\u6D77": "js/province/shanghai",
"\u5C71\u897F": "js/province/shanxi",
"\u9655\u897F": "js/province/shanxi1",
"\u56DB\u5DDD": "js/province/sichuan",
"\u53F0\u6E7E": "js/province/taiwan",
"\u5929\u6D25": "js/province/tianjin",
"\u9999\u6E2F": "js/province/xianggang",
"\u65B0\u7586": "js/province/xinjiang",
"\u897F\u85CF": "js/province/xizang",
"\u4E91\u5357": "js/province/yunnan",
"\u6D59\u6C5F": "js/province/zhejiang"
};
Object.entries(mapOptions).forEach(([displayName, pathFragment]) => {
const option = document.createElement("option");
option.value = pathFragment;
option.textContent = displayName;
selector.appendChild(option);
});
container.style.width = "100%";
container.style.height = "100%";
const chart = echarts.init(container, null, { renderer: "svg" });
function showLoading(message) {
chart.clear();
chart.showLoading("default", {
text: message,
color: "#4477cb",
textColor: "#333",
maskColor: "rgba(255, 255, 255, 0.8)",
zlevel: 0
});
}
function parseRgb(rgbString) {
var _a;
return ((_a = rgbString.match(/\d+/g)) == null ? void 0 : _a.map(Number)) || [0, 0, 0];
}
function createColorInputGroup(label, colorKey) {
const group = document.createElement("div");
group.className = "color-input-group";
const labelEl = document.createElement("label");
labelEl.textContent = label;
group.appendChild(labelEl);
const inputsContainer = document.createElement("div");
const [r, g, b] = parseRgb(colors[colorKey]);
const rInput = document.createElement("input");
rInput.type = "number";
rInput.min = "0";
rInput.max = "255";
rInput.value = String(r);
const gInput = document.createElement("input");
gInput.type = "number";
gInput.min = "0";
gInput.max = "255";
gInput.value = String(g);
const bInput = document.createElement("input");
bInput.type = "number";
bInput.min = "0";
bInput.max = "255";
bInput.value = String(b);
inputsContainer.append("R:", rInput, "G:", gInput, "B:", bInput);
group.appendChild(inputsContainer);
const updateColor = () => {
colors[colorKey] = `rgb(${rInput.value}, ${gInput.value}, ${bInput.value})`;
if (colorKey === "background") {
container.style.backgroundColor = colors.background;
}
};
rInput.addEventListener("input", updateColor);
gInput.addEventListener("input", updateColor);
bInput.addEventListener("input", updateColor);
return group;
}
function createHeightInputGroup() {
const group = document.createElement("div");
group.className = "color-input-group";
const labelEl = document.createElement("label");
labelEl.textContent = "\u9AD8\u5EA6 (px)";
group.appendChild(labelEl);
const input = document.createElement("input");
input.type = "number";
input.min = "200";
input.step = "10";
input.value = String(mapHeight);
input.style.width = "158px";
input.addEventListener("input", () => {
const newHeight = parseInt(input.value, 10);
if (!isNaN(newHeight) && newHeight >= 200) {
mapHeight = newHeight;
blockElement.style.height = `${mapHeight}px`;
chart.resize();
}
});
group.appendChild(input);
return group;
}
function buildSettingsPanel() {
settingsPanel.innerHTML = "";
settingsPanel.appendChild(createHeightInputGroup());
settingsPanel.appendChild(createColorInputGroup("\u80CC\u666F\u989C\u8272", "background"));
settingsPanel.appendChild(createColorInputGroup("\u5730\u56FE\u989C\u8272", "areaColor"));
settingsPanel.appendChild(createColorInputGroup("\u70B9\u4EAE\u989C\u8272", "litColor"));
const saveButton = document.createElement("button");
saveButton.textContent = "\u4FDD\u5B58\u8BBE\u7F6E";
saveButton.onclick = () => __async(null, null, function* () {
if (!blockId) return;
try {
yield fetch("/api/attr/setBlockAttrs", {
method: "POST",
body: JSON.stringify({
id: blockId,
attrs: {
"custom-map-colors": JSON.stringify(colors),
"custom-map-height": String(mapHeight)
}
})
});
yield fetch("/api/notification/pushMsg", {
method: "POST",
body: JSON.stringify({ msg: "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58" })
});
} catch (e) {
console.error("\u4FDD\u5B58\u8BBE\u7F6E\u5931\u8D25:", e);
}
});
settingsPanel.appendChild(saveButton);
}
function saveLitData() {
return __async(this, null, function* () {
if (!blockId) return;
try {
const dataToSave = {
regions: Array.from(litRegionsSet),
provinces: Array.from(litProvincesSet)
};
yield fetch("/api/attr/setBlockAttrs", {
method: "POST",
body: JSON.stringify({
id: blockId,
attrs: { "custom-map-lit-data": JSON.stringify(dataToSave) }
})
});
console.log("\u6210\u529F\u4FDD\u5B58\u70B9\u4EAE\u6570\u636E\u3002");
} catch (e) {
console.error("\u4FDD\u5B58\u70B9\u4EAE\u6570\u636E\u5931\u8D25:", e);
}
});
}
function renderChart(mapPathFragment) {
return __async(this, null, function* () {
currentMapPath = mapPathFragment;
showLoading("\u6B63\u5728\u52A0\u8F7D\u5730\u56FE...");
try {
const registeredMapName = yield loadAndRegisterMap(mapPathFragment);
const isChinaMap = mapPathFragment === "js/china";
const activeSet = isChinaMap ? litProvincesSet : litRegionsSet;
const mapData = echarts.getMap(registeredMapName).geoJSON.features.map((feature) => {
const name = feature.properties.name;
return { name, selected: activeSet.has(name) };
});
chart.hideLoading();
const option = {
tooltip: { trigger: "item", formatter: "{b}" },
geo: {
map: registeredMapName,
roam: true,
selectedMode: "multiple",
itemStyle: {
areaColor: colors.areaColor,
borderColor: "#ADADAD"
},
emphasis: {
focus: "none",
itemStyle: { areaColor: "#a9d0fa" }
},
select: {
itemStyle: {
areaColor: colors.litColor
}
},
regions: mapData
},
series: []
};
chart.setOption(option, true);
backButton.style.display = isChinaMap ? "none" : "block";
} catch (e) {
console.error(`\u6E32\u67D3\u5730\u56FE [${mapPathFragment}] \u5931\u8D25:`, e);
chart.hideLoading();
container.innerHTML = `<div class="error-msg">\u5730\u56FE\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u6309F12\u67E5\u770B\u63A7\u5236\u53F0\u3002</div>`;
}
});
}
chart.on("click", (params) => {
var _a;
if (!params.name) return;
const clickedName = params.name;
if (currentMapPath === "js/china") {
const targetPath = (_a = Object.entries(mapOptions).find(([displayName]) => displayName === clickedName)) == null ? void 0 : _a[1];
if (targetPath) {
selector.value = targetPath;
renderChart(targetPath);
}
return;
}
const currentRegisteredMapName = registeredMapsCache.get(currentMapPath);
if (!currentRegisteredMapName) return;
if (litRegionsSet.has(clickedName)) {
litRegionsSet.delete(clickedName);
const provinceGeoJSON = echarts.getMap(currentRegisteredMapName).geoJSON;
const citiesInProvince = provinceGeoJSON.features.map((f) => f.properties.name);
const hasOtherLitCities = citiesInProvince.some((city) => litRegionsSet.has(city));
if (!hasOtherLitCities) {
litProvincesSet.delete(currentRegisteredMapName);
}
} else {
litRegionsSet.add(clickedName);
litProvincesSet.add(currentRegisteredMapName);
}
saveLitData();
renderChart(currentMapPath);
});
backButton.addEventListener("click", () => {
selector.value = "js/china";
renderChart("js/china");
});
selector.addEventListener("change", (e) => {
const value = e.target.value;
if (value === "special/settings") {
container.style.display = "none";
backButton.style.display = "none";
settingsPanel.style.display = "flex";
settingsPanel.style.flexDirection = "column";
settingsPanel.style.justifyContent = "center";
settingsPanel.style.alignItems = "center";
settingsPanel.style.height = "100%";
settingsPanel.style.gap = "15px";
buildSettingsPanel();
} else {
container.style.display = "block";
settingsPanel.style.display = "none";
renderChart(value);
}
});
const resizeObserver = new ResizeObserver(() => chart.resize());
resizeObserver.observe(container);
function initialLoad() {
return __async(this, null, function* () {
if (blockId) {
try {
const response = yield fetch("/api/attr/getBlockAttrs", {
method: "POST",
body: JSON.stringify({ id: blockId })
});
const res = yield response.json();
if (res.code === 0) {
if (res.data["custom-map-colors"]) {
const savedColors = JSON.parse(res.data["custom-map-colors"]);
Object.assign(colors, savedColors);
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u989C\u8272\u8BBE\u7F6E\u3002");
}
if (res.data["custom-map-height"]) {
const savedHeight = parseInt(res.data["custom-map-height"], 10);
if (!isNaN(savedHeight) && savedHeight >= 200) {
mapHeight = savedHeight;
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u9AD8\u5EA6\u8BBE\u7F6E\u3002");
}
}
if (res.data["custom-map-lit-data"]) {
const savedLitData = JSON.parse(res.data["custom-map-lit-data"]);
if (savedLitData.regions) {
savedLitData.regions.forEach((region) => litRegionsSet.add(region));
}
if (savedLitData.provinces) {
savedLitData.provinces.forEach((province) => litProvincesSet.add(province));
}
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u70B9\u4EAE\u6570\u636E\u3002");
}
}
} catch (e) {
console.error("\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u5C5E\u6027\u5931\u8D25:", e);
}
}
blockElement.style.height = `${mapHeight}px`;
container.style.backgroundColor = colors.background;
renderChart("js/china");
});
}
initialLoad();
}
const checkInterval = 100;
const timeout = 1e3;
let elapsedTime = 0;
const self = this;
const intervalId = setInterval(() => {
const echartsInstance = window.echarts;
if (echartsInstance && typeof echartsInstance.init === "function") {
clearInterval(intervalId);
try {
initializeApp(self, echartsInstance);
} catch (e) {
console.error("\u521D\u59CB\u5316\u5730\u56FE\u5757\u5931\u8D25:", e);
self.innerHTML = `<div class="error-msg">\u521D\u59CB\u5316\u5730\u56FE\u5757\u5931\u8D25\uFF0C\u8BE6\u60C5\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u3002</div>`;
}
} else {
elapsedTime += checkInterval;
if (elapsedTime > timeout) {
clearInterval(intervalId);
console.error("\u7B49\u5F85\u539F\u751F ECharts \u5E93\u52A0\u8F7D\u8D85\u65F6\u3002");
self.innerHTML = `<div class="error-msg">\u539F\u751F ECharts \u5E93\u52A0\u8F7D\u8D85\u65F6\u3002\u8BF7\u786E\u4FDD\u6587\u6863\u4E2D\u5B58\u5728\u4E00\u4E2A\u5B98\u65B9\u56FE\u8868\u5757\u3002</div>`;
}
}
}, checkInterval);
在线地图版自定义块 js (可以不用下载 map)
/******/ "use strict";
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function initializeApp(blockElement, echarts) {
const blockId = blockElement.dataset.nodeId;
let mapHeight = 600;
const colors = {
background: "rgb(255, 255, 255)",
areaColor: "rgb(231, 232, 234)",
litColor: "rgb(244, 208, 63)"
};
const registeredMapsCache = /* @__PURE__ */ new Map();
const litRegionsSet = /* @__PURE__ */ new Set();
const litProvincesSet = /* @__PURE__ */ new Set();
let currentMapPath = "js/china";
function loadAndRegisterMap(mapPathFragment) {
return __async(this, null, function* () {
if (registeredMapsCache.has(mapPathFragment)) {
const cachedName = registeredMapsCache.get(mapPathFragment);
return Promise.resolve(cachedName);
}
const localSrc = `/assets/map/${mapPathFragment}.js?v=${Date.now()}`;
const cdnSrc = `https://cdn.jsdelivr.net/npm/echarts/map/${mapPathFragment}.js`;
const originalRegisterMap = echarts.registerMap;
let capturedName = null;
return new Promise((resolve, reject) => {
echarts.registerMap = (name, data) => {
originalRegisterMap.call(echarts, name, data);
if (echarts.getMap(name)) {
capturedName = name;
}
};
const tryLoad = (src, isFallback = false) => {
const script = document.createElement("script");
script.src = src;
script.onload = () => {
echarts.registerMap = originalRegisterMap;
document.head.removeChild(script);
if (capturedName) {
registeredMapsCache.set(mapPathFragment, capturedName);
resolve(capturedName);
} else {
const mapNameFromFile = mapPathFragment.split("/").pop();
reject(new Error(`\u672A\u80FD\u6355\u83B7\u5730\u56FE [${mapNameFromFile}] \u7684\u6CE8\u518C\u3002`));
}
};
script.onerror = () => {
document.head.removeChild(script);
if (!isFallback) {
console.warn(`\u672C\u5730\u5730\u56FE [${localSrc}] \u52A0\u8F7D\u5931\u8D25, \u6B63\u5728\u5C1D\u8BD5\u4ECE CDN \u52A0\u8F7D...`);
tryLoad(cdnSrc, true);
} else {
echarts.registerMap = originalRegisterMap;
reject(new Error(`\u52A0\u8F7D\u5730\u56FE\u811A\u672C [${src}] \u5931\u8D25\u3002`));
}
};
document.head.appendChild(script);
};
tryLoad(localSrc);
});
});
}
blockElement.innerHTML = "";
blockElement.className = "qianqian-map-block";
blockElement.style.position = "relative";
const container = document.createElement("div");
container.className = "map-container";
const selector = document.createElement("select");
selector.className = "map-selector";
const backButton = document.createElement("button");
backButton.className = "back-button";
backButton.textContent = "\u8FD4\u56DE";
backButton.style.display = "none";
backButton.style.position = "absolute";
backButton.style.top = "10px";
backButton.style.right = "10px";
backButton.style.zIndex = "10";
const settingsPanel = document.createElement("div");
settingsPanel.className = "settings-panel";
settingsPanel.style.display = "none";
blockElement.append(selector, backButton, container, settingsPanel);
const mapOptions = {
"\u4E2D\u56FD": "js/china",
"\u8BBE\u7F6E": "special/settings",
"\u5B89\u5FBD": "js/province/anhui",
"\u6FB3\u95E8": "js/province/aomen",
"\u5317\u4EAC": "js/province/beijing",
"\u91CD\u5E86": "js/province/chongqing",
"\u798F\u5EFA": "js/province/fujian",
"\u7518\u8083": "js/province/gansu",
"\u5E7F\u4E1C": "js/province/guangdong",
"\u5E7F\u897F": "js/province/guangxi",
"\u8D35\u5DDE": "js/province/guizhou",
"\u6D77\u5357": "js/province/hainan",
"\u6CB3\u5317": "js/province/hebei",
"\u9ED1\u9F99\u6C5F": "js/province/heilongjiang",
"\u6CB3\u5357": "js/province/henan",
"\u6E56\u5317": "js/province/hubei",
"\u6E56\u5357": "js/province/hunan",
"\u6C5F\u82CF": "js/province/jiangsu",
"\u6C5F\u897F": "js/province/jiangxi",
"\u5409\u6797": "js/province/jilin",
"\u8FBD\u5B81": "js/province/liaoning",
"\u5185\u8499\u53E4": "js/province/neimenggu",
"\u5B81\u590F": "js/province/ningxia",
"\u9752\u6D77": "js/province/qinghai",
"\u5C71\u4E1C": "js/province/shandong",
"\u4E0A\u6D77": "js/province/shanghai",
"\u5C71\u897F": "js/province/shanxi",
"\u9655\u897F": "js/province/shanxi1",
"\u56DB\u5DDD": "js/province/sichuan",
"\u53F0\u6E7E": "js/province/taiwan",
"\u5929\u6D25": "js/province/tianjin",
"\u9999\u6E2F": "js/province/xianggang",
"\u65B0\u7586": "js/province/xinjiang",
"\u897F\u85CF": "js/province/xizang",
"\u4E91\u5357": "js/province/yunnan",
"\u6D59\u6C5F": "js/province/zhejiang"
};
Object.entries(mapOptions).forEach(([displayName, pathFragment]) => {
const option = document.createElement("option");
option.value = pathFragment;
option.textContent = displayName;
selector.appendChild(option);
});
container.style.width = "100%";
container.style.height = "100%";
const chart = echarts.init(container, null, { renderer: "svg" });
function showLoading(message) {
chart.clear();
chart.showLoading("default", {
text: message,
color: "#4477cb",
textColor: "#333",
maskColor: "rgba(255, 255, 255, 0.8)",
zlevel: 0
});
}
function parseRgb(rgbString) {
var _a;
return ((_a = rgbString.match(/\d+/g)) == null ? void 0 : _a.map(Number)) || [0, 0, 0];
}
function createColorInputGroup(label, colorKey) {
const group = document.createElement("div");
group.className = "color-input-group";
const labelEl = document.createElement("label");
labelEl.textContent = label;
group.appendChild(labelEl);
const inputsContainer = document.createElement("div");
const [r, g, b] = parseRgb(colors[colorKey]);
const rInput = document.createElement("input");
rInput.type = "number";
rInput.min = "0";
rInput.max = "255";
rInput.value = String(r);
const gInput = document.createElement("input");
gInput.type = "number";
gInput.min = "0";
gInput.max = "255";
gInput.value = String(g);
const bInput = document.createElement("input");
bInput.type = "number";
bInput.min = "0";
bInput.max = "255";
bInput.value = String(b);
inputsContainer.append("R:", rInput, "G:", gInput, "B:", bInput);
group.appendChild(inputsContainer);
const updateColor = () => {
colors[colorKey] = `rgb(${rInput.value}, ${gInput.value}, ${bInput.value})`;
if (colorKey === "background") {
container.style.backgroundColor = colors.background;
}
};
rInput.addEventListener("input", updateColor);
gInput.addEventListener("input", updateColor);
bInput.addEventListener("input", updateColor);
return group;
}
function createHeightInputGroup() {
const group = document.createElement("div");
group.className = "color-input-group";
const labelEl = document.createElement("label");
labelEl.textContent = "\u9AD8\u5EA6 (px)";
group.appendChild(labelEl);
const input = document.createElement("input");
input.type = "number";
input.min = "200";
input.step = "10";
input.value = String(mapHeight);
input.style.width = "158px";
input.addEventListener("input", () => {
const newHeight = parseInt(input.value, 10);
if (!isNaN(newHeight) && newHeight >= 200) {
mapHeight = newHeight;
blockElement.style.height = `${mapHeight}px`;
chart.resize();
}
});
group.appendChild(input);
return group;
}
function buildSettingsPanel() {
settingsPanel.innerHTML = "";
settingsPanel.appendChild(createHeightInputGroup());
settingsPanel.appendChild(createColorInputGroup("\u80CC\u666F\u989C\u8272", "background"));
settingsPanel.appendChild(createColorInputGroup("\u5730\u56FE\u989C\u8272", "areaColor"));
settingsPanel.appendChild(createColorInputGroup("\u70B9\u4EAE\u989C\u8272", "litColor"));
const saveButton = document.createElement("button");
saveButton.textContent = "\u4FDD\u5B58\u8BBE\u7F6E";
saveButton.onclick = () => __async(null, null, function* () {
if (!blockId) return;
try {
yield fetch("/api/attr/setBlockAttrs", {
method: "POST",
body: JSON.stringify({
id: blockId,
attrs: {
"custom-map-colors": JSON.stringify(colors),
"custom-map-height": String(mapHeight)
}
})
});
yield fetch("/api/notification/pushMsg", {
method: "POST",
body: JSON.stringify({ msg: "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58" })
});
} catch (e) {
console.error("\u4FDD\u5B58\u8BBE\u7F6E\u5931\u8D25:", e);
}
});
settingsPanel.appendChild(saveButton);
}
function saveLitData() {
return __async(this, null, function* () {
if (!blockId) return;
try {
const dataToSave = {
regions: Array.from(litRegionsSet),
provinces: Array.from(litProvincesSet)
};
yield fetch("/api/attr/setBlockAttrs", {
method: "POST",
body: JSON.stringify({
id: blockId,
attrs: { "custom-map-lit-data": JSON.stringify(dataToSave) }
})
});
console.log("\u6210\u529F\u4FDD\u5B58\u70B9\u4EAE\u6570\u636E\u3002");
} catch (e) {
console.error("\u4FDD\u5B58\u70B9\u4EAE\u6570\u636E\u5931\u8D25:", e);
}
});
}
function renderChart(mapPathFragment) {
return __async(this, null, function* () {
currentMapPath = mapPathFragment;
showLoading("\u6B63\u5728\u52A0\u8F7D\u5730\u56FE...");
try {
const registeredMapName = yield loadAndRegisterMap(mapPathFragment);
const isChinaMap = mapPathFragment === "js/china";
const activeSet = isChinaMap ? litProvincesSet : litRegionsSet;
const mapData = echarts.getMap(registeredMapName).geoJSON.features.map((feature) => {
const name = feature.properties.name;
return { name, selected: activeSet.has(name) };
});
chart.hideLoading();
const option = {
tooltip: { trigger: "item", formatter: "{b}" },
geo: {
map: registeredMapName,
roam: true,
selectedMode: "multiple",
itemStyle: {
areaColor: colors.areaColor,
borderColor: "#ADADAD"
},
emphasis: {
focus: "none",
itemStyle: { areaColor: "#a9d0fa" }
},
select: {
itemStyle: {
areaColor: colors.litColor
}
},
regions: mapData
},
series: []
};
chart.setOption(option, true);
backButton.style.display = isChinaMap ? "none" : "block";
} catch (e) {
console.error(`\u6E32\u67D3\u5730\u56FE [${mapPathFragment}] \u5931\u8D25:`, e);
chart.hideLoading();
container.innerHTML = `<div class="error-msg">\u5730\u56FE\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u6309F12\u67E5\u770B\u63A7\u5236\u53F0\u3002</div>`;
}
});
}
chart.on("click", (params) => {
var _a;
if (!params.name) return;
const clickedName = params.name;
if (currentMapPath === "js/china") {
const targetPath = (_a = Object.entries(mapOptions).find(([displayName]) => displayName === clickedName)) == null ? void 0 : _a[1];
if (targetPath) {
selector.value = targetPath;
renderChart(targetPath);
}
return;
}
const currentRegisteredMapName = registeredMapsCache.get(currentMapPath);
if (!currentRegisteredMapName) return;
if (litRegionsSet.has(clickedName)) {
litRegionsSet.delete(clickedName);
const provinceGeoJSON = echarts.getMap(currentRegisteredMapName).geoJSON;
const citiesInProvince = provinceGeoJSON.features.map((f) => f.properties.name);
const hasOtherLitCities = citiesInProvince.some((city) => litRegionsSet.has(city));
if (!hasOtherLitCities) {
litProvincesSet.delete(currentRegisteredMapName);
}
} else {
litRegionsSet.add(clickedName);
litProvincesSet.add(currentRegisteredMapName);
}
saveLitData();
renderChart(currentMapPath);
});
backButton.addEventListener("click", () => {
selector.value = "js/china";
renderChart("js/china");
});
selector.addEventListener("change", (e) => {
const value = e.target.value;
if (value === "special/settings") {
container.style.display = "none";
backButton.style.display = "none";
settingsPanel.style.display = "flex";
settingsPanel.style.flexDirection = "column";
settingsPanel.style.justifyContent = "center";
settingsPanel.style.alignItems = "center";
settingsPanel.style.height = "100%";
settingsPanel.style.gap = "15px";
buildSettingsPanel();
} else {
container.style.display = "block";
settingsPanel.style.display = "none";
renderChart(value);
}
});
const resizeObserver = new ResizeObserver(() => chart.resize());
resizeObserver.observe(container);
function initialLoad() {
return __async(this, null, function* () {
if (blockId) {
try {
const response = yield fetch("/api/attr/getBlockAttrs", {
method: "POST",
body: JSON.stringify({ id: blockId })
});
const res = yield response.json();
if (res.code === 0) {
if (res.data["custom-map-colors"]) {
const savedColors = JSON.parse(res.data["custom-map-colors"]);
Object.assign(colors, savedColors);
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u989C\u8272\u8BBE\u7F6E\u3002");
}
if (res.data["custom-map-height"]) {
const savedHeight = parseInt(res.data["custom-map-height"], 10);
if (!isNaN(savedHeight) && savedHeight >= 200) {
mapHeight = savedHeight;
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u9AD8\u5EA6\u8BBE\u7F6E\u3002");
}
}
if (res.data["custom-map-lit-data"]) {
const savedLitData = JSON.parse(res.data["custom-map-lit-data"]);
if (savedLitData.regions) {
savedLitData.regions.forEach((region) => litRegionsSet.add(region));
}
if (savedLitData.provinces) {
savedLitData.provinces.forEach((province) => litProvincesSet.add(province));
}
console.log("\u6210\u529F\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u70B9\u4EAE\u6570\u636E\u3002");
}
}
} catch (e) {
console.error("\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u7684\u5C5E\u6027\u5931\u8D25:", e);
}
}
blockElement.style.height = `${mapHeight}px`;
container.style.backgroundColor = colors.background;
renderChart("js/china");
});
}
initialLoad();
}
const checkInterval = 100;
const timeout = 1e3;
let elapsedTime = 0;
const self = this;
const intervalId = setInterval(() => {
const echartsInstance = window.echarts;
if (echartsInstance && typeof echartsInstance.init === "function") {
clearInterval(intervalId);
try {
initializeApp(self, echartsInstance);
} catch (e) {
console.error("\u521D\u59CB\u5316\u5730\u56FE\u5757\u5931\u8D25:", e);
self.innerHTML = `<div class="error-msg">\u521D\u59CB\u5316\u5730\u56FE\u5757\u5931\u8D25\uFF0C\u8BE6\u60C5\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u3002</div>`;
}
} else {
elapsedTime += checkInterval;
if (elapsedTime > timeout) {
clearInterval(intervalId);
console.error("\u7B49\u5F85\u539F\u751F ECharts \u5E93\u52A0\u8F7D\u8D85\u65F6\u3002");
self.innerHTML = `<div class="error-msg">\u539F\u751F ECharts \u5E93\u52A0\u8F7D\u8D85\u65F6\u3002\u8BF7\u786E\u4FDD\u6587\u6863\u4E2D\u5B58\u5728\u4E00\u4E2A\u5B98\u65B9\u56FE\u8868\u5757\u3002</div>`;
}
}
}, checkInterval);
开始记录你的旅游足迹吧!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于