在數據大屏、後台儀表盤、地理統計報表中,將數據映射到地圖區域並通過鼠標交互展示詳情,是極具直觀性的呈現方式。本文基於 Raphael.js + jQuery 實現中國地圖 SVG 繪製、數據動態載入、Tooltip 跟隨交互完整方案。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>中國地圖數據可視化</title>
<script src="https://cdn.jsdelivr.net/npm/raphael@2.3.0/raphael.min.js"></script>
<script src="chinamapPath.js"></script> <!-- 省份路徑數據 -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<style>
#map { width: 100%; height: 600px; }
#tip {
position: absolute; width: 200px; display: none; z-index: 999;
border: 1px solid #ddd; background: #fff; border-radius: 6px;
box-shadow: 2px 2px 8px rgba(0,0,0,.15); padding: 8px 12px;
font-size: 14px; line-height: 1.6;
}
#tip h4 { margin: 0 0 6px; font-size: 15px; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px; }
</style>
</head>
<body>
<div id="map"></div>
<div id="tip"></div>
</body>
</html>
<script>
$(function() {
// 1. 初始化 Raphael 畫布
var R = Raphael("map", "100%", 600);
var attrs = { fill: "#eee", stroke: "#fff", "stroke-width": 1, "stroke-opacity": 0.5 };
var china = {}; // 存儲各省份 path 對象
// 2. 繪製所有省份路徑
for (var code in chinaMapPaths) { // 假設 chinamapPath.js 暴露 chinaMapPaths 對象
var pathStr = chinaMapPaths[code].path;
var name = chinaMapPaths[code].name;
var pathObj = R.path(pathStr).attr(attrs);
china[code] = { path: pathObj, name: name };
}
// 3. 異步載入統計數據
$.getJSON("json.php", function(data) {
// data 結構: [{province: '北京', value: 12345}, ...]
var values = data.map(function(d) { return d.value; });
var maxVal = Math.max.apply(null, values);
var minVal = Math.min.apply(null, values);
// 4. 顏色映射函數 (簡單線性漸變)
var colorScale = function(val) {
var ratio = (val - minVal) / (maxVal - minVal || 1);
var r = Math.round(200 + 55 * ratio); // 200-255
var g = Math.round(200 - 150 * ratio); // 50-200
var b = 50;
return "rgb(" + r + "," + g + "," + b + ")";
};
// 5. 綁定交互事件
var $tip = $("#tip");
var xOffset = 15, yOffset = 20; // Tooltip 相對鼠標偏移
for (var code in china) {
var province = china[code];
var item = data.find(function(d) { return d.province === province.name; });
var val = item ? item.value : 0;
var fillColor = colorScale(val);
province.path.attr({ fill: fillColor });
(function(st, name, value, baseColor) {
// 鼠標進入
st.hover(
function(e) {
st.animate({ fill: "#ffeb3b", stroke: "#fff" }, 300);
$tip.html("" + name + "
活躍用戶:" + value.toLocaleString() + "
")
.css({ top: e.pageY - yOffset, left: e.pageX + xOffset })
.fadeIn(200);
},
// 鼠標離開
function() {
st.animate({ fill: baseColor, stroke: "#fff" }, 300);
$tip.fadeOut(150);
}
);
// 鼠標移動 (Tooltip 跟隨)
st.mousemove(function(e) {
$tip.css({ top: e.pageY - yOffset, left: e.pageX + xOffset });
});
})(province.path, province.name, val, fillColor);
}
});
});
</script>
<?php
// json.php
header('Content-Type: application/json; charset=utf-8');
// 模擬數據來源:實際從 MySQL/Redis/ES 查詢
$data = [
['province' => '北京', 'value' => 25800],
['province' => '上海', 'value' => 23400],
['province' => '廣東', 'value' => 45600],
['province' => '浙江', 'value' => 18900],
['province' => '江蘇', 'value' => 22100],
// ... 其他省份
];
echo json_encode($data);
hover (顯示/隱藏) 和 mousemove (位置更新),避免省份區域較大時 Tooltip 固定位置導致遮擋或遠離鼠標。animate({fill: ...}, 300) 讓顏色過渡自然,減少閃爍感。R.safari() 處理舊版 WebKit 重繪 Bug,現代瀏覽器可省略。maxVal === minVal 邊界,避免除零。R.setSize(w, h) 重算畫布,Path 自動縮放。<path> 添加 aria-label、鍵盤焦點樣式、高對比度模式。