trtoi / static /js /analytics.js
plokmii's picture
deploy TRTOI website (read-only public site)
db3c808 verified
Raw
History Blame Contribute Delete
3.97 kB
/* 流量統計:每日點擊長條圖(Chart.js)+ 全球訪客地圖(jsVectorMap)。 */
(function () {
"use strict";
var el = document.getElementById("analyticsData");
if (!el) return;
var data;
try { data = JSON.parse(el.textContent); } catch (e) { return; }
var TA = window.T_AN || { times: "次", sep: ":" }; // 依語言的單位/分隔字
// ---- 點擊趨勢(日 / 週 / 月 可切換)----
var dc = document.getElementById("dailyChart");
if (dc && typeof Chart !== "undefined") {
var series = data.series || { day: [], week: [], month: [] };
var chart = null;
function render(range) {
var s = series[range] || [];
if (chart) chart.destroy();
chart = new Chart(dc, {
type: "bar",
data: {
labels: s.map(function (x) { return x.label; }),
datasets: [{ data: s.map(function (x) { return x.hits; }), backgroundColor: "#8a1f2b" }]
},
options: {
responsive: true, maintainAspectRatio: false,
plugins: { legend: { display: false }, tooltip: { callbacks: { label: function (c) { return c.parsed.y + " " + TA.times; } } } },
scales: { x: { grid: { display: false } }, y: { beginAtZero: true, ticks: { precision: 0 } } }
}
});
}
render("day");
document.querySelectorAll(".range-btn").forEach(function (b) {
b.addEventListener("click", function () {
document.querySelectorAll(".range-btn").forEach(function (x) { x.classList.remove("active"); });
b.classList.add("active");
render(b.getAttribute("data-range"));
});
});
}
// ---- 全球訪客地圖(jsVectorMap,依國家點擊數上色 choropleth)----
var wm = document.getElementById("worldMap");
if (wm && typeof jsVectorMap !== "undefined" && data.countries && data.countries.length) {
var byCode = {}, maxH = 0;
data.countries.forEach(function (c) { byCode[c.cc] = c; if (c.hits > maxH) maxH = c.hits; });
function lerp(a, b, t) { return Math.round(a + (b - a) * t); }
function colorFor(hits) { // 淺紅→深紅;次數越多越深
var t = 0.28 + 0.72 * (maxH ? hits / maxH : 1);
return "rgb(" + lerp(236, 138, t) + "," + lerp(202, 31, t) + "," + lerp(206, 43, t) + ")";
}
try {
new jsVectorMap({
selector: "#worldMap",
map: "world",
zoomButtons: true,
zoomOnScroll: false,
backgroundColor: "transparent",
regionStyle: {
initial: { fill: "#e6e4df", stroke: "#ffffff", "stroke-width": 0.4 }, // 無資料:淺灰
hover: { fillOpacity: 0.75 }
},
onRegionTooltipShow: function (event, tooltip, code) {
var info = byCode[code];
if (info) tooltip.text(info.country + TA.sep + info.hits + " " + TA.times, true);
}
});
// 直接把有訪客的國家上色(避開套件色階對單一數值的 bug);用「重試輪詢」而非單次
// setTimeout:地圖 SVG 有時渲染較慢(冷載入/CDN 未快取,英文頁較常見),
// 單次上色會在區塊還沒出現前就跑掉 → 地圖不變色。改成每 120ms 重試、最多 ~3 秒,
// 直到每個有訪客國家的區塊都存在並上色。!important 確保不被 hover/mouseout 覆蓋。
function colorize(tries) {
var svg = wm.querySelector("svg");
var allDone = !!svg;
if (svg) {
data.countries.forEach(function (c) {
var el = svg.querySelector('[data-code="' + c.cc + '"]');
if (el) el.style.setProperty("fill", colorFor(c.hits), "important");
else allDone = false;
});
}
if (!allDone && tries > 0) setTimeout(function () { colorize(tries - 1); }, 120);
}
colorize(25);
} catch (e) {
// 若地圖套件載入失敗,靜默略過(下方仍有國家排行清單)
}
}
})();