首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP + Raphael.js 實現中國地圖數據可視化

     編輯:PHP 相關知識

結合 PHP 後端數據輸出、Raphael.js SVG 繪圖庫、jQuery 交互,實現省級數據的中國地圖熱力圖展示。本文提供完整前後端代碼架構。

技術棧

  • 後端:PHP + MySQL → JSON API
  • 前端:Raphael.js (SVG) + jQuery (AJAX)
  • 數據:各省活躍用戶數 → 6 級顏色映射

文件結構

project/
├── index.html      # 頁面入口
├── json.php        # 數據 API
├── raphael.js      # Raphael 庫
├── chinamapPath.js # 省份路徑數據
└── jquery.js       # jQuery 庫

1. HTML 容器

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>中國地圖數據可視化</title>
    <script src="jquery.js"></script>
    <script src="raphael.js"></script>
    <script src="chinamapPath.js"></script>
</head>
<body>
    <div id="map" style="width: 600px; height: 500px;"></div>
</body>
</html>

2. PHP 數據接口 (json.php)

<?php
// json.php
header('Content-Type: application/json; charset=utf-8');

$host = 'localhost';
$user = 'root';
$pass = '';
$dbname = 'demo';

$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
    echo json_encode(['error' => 'DB連接失敗']);
    exit;
}
$mysqli->set_charset('utf8mb4');

// 關鍵:查詢順序必須與 chinamapPath.js 省份順序一致
$sql = "SELECT active FROM mapdata ORDER BY id ASC";
$result = $mysqli->query($sql);

$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = (int)$row['active'];
}

echo json_encode($data); // 輸出: [120, 45, 300, ...]
$mysqli->close();
?>

MySQL 表結構

CREATE TABLE mapdata (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    province VARCHAR(20) NOT NULL COMMENT '省份名稱',
    active INT UNSIGNED DEFAULT 0 COMMENT '活躍用戶數',
    INDEX idx_province (province)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入數據 (順序對應 chinamapPath.js)
INSERT INTO mapdata (province, active) VALUES
('北京', 1200), ('天津', 800), ('河北', 1500), ...;

3. 前端渲染邏輯 (內嵌 index.html 或獨立 map.js)

<script>
$(function() {
    $.get('json.php', function(json) {
        // 兼容字符串/數組
        var data = typeof json === 'string' ? JSON.parse(json) : json;
        
        // 1. 數值映射到 0-5 級
        var levels = [];
        for (var i = 0; i < data.length; i++) {
            var d = data[i];
            if (d < 100) level = 0;
            else if (d < 500) level = 1;
            else if (d < 2000) level = 2;
            else if (d < 5000) level = 3;
            else if (d < 10000) level = 4;
            else level = 5;
            levels.push(level);
        }
        
        // 2. 顏色定義 (淺到深)
        var colors = [
            '#d7eef8', '#97d6f5', '#3fbeef', 
            '#00a2e9', '#0084be', '#005c86'
        ];
        
        // 3. 初始化 Raphael
        var R = Raphael('map', 600, 500);
        
        // 4. 繪制地圖 (假設 chinamapPath.js 定義 window.china 對象)
        paintMap(R); // 此函數來自 chinamapPath.js 或自定義
        
        // 5. 文字屬性
        var textAttr = {
            fill: '#000',
            'font-size': '12px',
            cursor: 'pointer'
        };
        
        // 6. 遍歷省份填充顏色、添加標籤、綁定交互
        var i = 0;
        for (var state in china) {
            var st = china[state]['path'];
            var name = china[state]['name'];
            
            // 獲取中心坐標 (用於放置文字)
            var bbox = st.getBBox();
            var cx = bbox.x + bbox.width / 2;
            var cy = bbox.y + bbox.height / 2;
            
            // 微調特定省份文字位置
            var offsets = {
                '江蘇': [5, -10], '河北': [-10, 20], '天津': [10, 10],
                '上海': [10, 0], '廣東': [0, -10], '澳門': [0, 10],
                '香港': [20, 5], '甘肅': [-40, -30], '陝西': [5, 10],
                '內蒙古': [-15, 65]
            };
            if (offsets[name]) {
                cx += offsets[name][0];
                cy += offsets[name][1];
            }
            
            // 創建文字標籤
            china[state]['text'] = R.text(cx, cy, name).attr(textAttr);
            
            // 填充顏色
            var fillColor = colors[levels[i]];
            st.attr({fill: fillColor, stroke: '#eee', 'stroke-width': 0.5});
            
            // 懸停交互
            st[0].onmouseover = function() {
                this.animate({fill: '#fdd', stroke: '#eee'}, 300);
                china[state]['text'].toFront();
            };
            st[0].onmouseout = function() {
                this.animate({fill: fillColor, stroke: '#eee'}, 300);
                china[state]['text'].toFront();
            };
            
            i++;
        }
    });
});

// 輔助:字符串轉數組 (舊版兼容)
function string2Array(str) {
    return JSON.parse(str);
}
</script>

4. chinamapPath.js 關鍵數據結構

// 簡化示例,實際文件包含所有省份 SVG 路徑
var china = {
    '北京': {
        name: '北京',
        path: R.path('M...Z'), // SVG 路徑字符串
        text: null
    },
    '天津': { ... },
    // ... 34 個省級行政區
};

完整路徑數據可從開源項目獲取:china-map-data

進階優化建議

  1. 數據緩存:PHP 輸出添加 header('Cache-Control: max-age=300')
  2. 顏色插值:使用 D3.js scaleQuantize 或 scaleThreshold 替代硬編碼級別
  3. 響應式:R.setViewBox(0, 0, 600, 500, true) 適配容器
  4. 提示框:懸停顯示詳細數值、排名、趨勢圖
  5. 圖例組件:展示顏色等級對應數值範圍
  6. 現代替代:ECharts China Map / Highcharts Map / AntV L7 更強大易用

完整 Demo 效果

地圖可視化效果圖

此方案展示了經典「後端數據 + 前端 SVG 繪製」架構,理解原理後建議遷移至成熟圖表庫提升開發效率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved