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

Flash 資料視覺化史話:從 libswf/Ming 到現代 Canvas/SVG/WebGL 方案

     編輯:PHP 綜合知識

歷史背景:PHP 與 Flash 的短暫蜜月期

文章撰寫於 2000 年代前期,展示使用 **PHP `libswf` 擴充模組 (Ming)** 動態產生 **SWF (Shockwave Flash)** 檔案,繪製餅圖視覺化資料。當時 Flash Player 滲透率 > 90%,向量繪圖、動畫、互動性遠超 HTML/JavaScript (IE 6 時代)。

關鍵技術棧回顧

元件說明現狀
libswf / MingC 函式庫 + PHP 擴充,提供 `swf_openfile`, `swf_ortho2`, `swf_shapearc`, `swf_definetext` 等底層繪圖 APIPHP 5.3 移除 (Ming 獨立專案仍存但無人維護)
SWF 格式二進位向量圖形/動畫格式,需 Flash Player 播放Adobe 2020/12/31 終止支援,瀏覽器全面封鎖
字體處理Type 1 字體轉換工具、/usr/local/swf/fonts/ 目錄需 Web Server 讀取權限現代用 Web Fonts (WOFF2) + CSS `@font-face`
資料來源MySQL `city` 表,`city_id`, `city_name`, `city_timestamp`標準關聯式資料庫查詢
輸出方式swf_openfile("city.swf", ...) 寫檔 → HTML ``現代:API 回傳 JSON → 前端 Chart.js/D3/ECharts 渲染

原始餅圖類別邏輯分析 (`flash_pie`)

class flash_pie {
    var $r_arr = [0.1, 1, 0, 1, 0, 1, 0.388, 0.4, 0.388, 0.929]; // 顏色 R
    var $g_arr = [1, 0, 0, 1, 1, 0, 0.8, 0.4, 0.8, 0.439];     // 顏色 G
    var $b_arr = [0.25, 0, 1, 0, 1, 1, 1, 0.4, 1, 0.043];      // 顏色 B

    function flash_pie($values, $this_file) {
        swf_openfile($this_file, 1000, 450, 30, 1, 1, 1); // 寫檔
        swf_ortho2(-400, 300, -90, 250); // 座標系
        swf_definefont(10, "Mod"); // 字體
        // 計算總和、各扇區角度 (度數)
        // 迴圈呼叫 show_slice($i, $objID, $begin, $end)
    }
    function show_slice($i, $objID, $begin, $end) {
        swf_addcolor($this->r_arr[$i], $this->g_arr[$i], $this->b_arr[$i], 1);
        swf_startshape($objID);
        swf_shapefillsolid(0,0,0,1);
        swf_shapearc(0, 0, 100, $begin, $end); // 畫圓弧
        swf_shapecurveto(0, 0, 0, 0); // 閉合到中心
        swf_endshape($objID);
        swf_pushmatrix(); swf_placeobject($objID, 1); swf_popmatrix();
        swf_showframe(); // 每扇區一幀
    }
    // pie_legend, pie_text, pie_title, show, close 同理...
}

核心繪圖邏輯 (可移植至 Canvas/SVG)

  1. 資料正規化:`$val = $values[$i] / $sum` → 百分比。
  2. 極座標角度:`$begin` 累積起始角度、`$end = $begin + $val * 360` 結束角度。
  3. 路徑構建:移動到中心 (0,0) → 畫圓弧 `arc(0, 0, radius, startRad, endRad)` → 連線回中心 `lineTo(0,0)` → 閉合 `closePath()`。
  4. 圖例佈局:色塊 + 文字標籤 (含百分比),垂直堆疊。

現代化替代方案完整對照

方案 A:前端渲染 (主流、推薦)

**PHP 只負責輸出 JSON 資料**,前端使用成熟圖表庫:

圖表庫特色授權適合場景
Chart.jsCanvas、簡單易用、響應式、動畫流暢、Tree-shakableMIT儀表板、報表、簡單圖表
EChartsCanvas/SVG、功能極豐富 (地圖、3D、流向、關係圖)、主題系統Apache 2.0複雜大屏、地理視覺化、企業級 BI
D3.jsSVG、資料驅動文檔、底層控制力最強、學習曲線陡峭BSD-3高度客製化、學術視覺化、特殊圖表
Apache ECharts / AntV G2Grammar of Graphics、TypeScript 優先、React/Vue 整合佳MIT/Apache現代前端專案、型別安全
<!-- PHP API: /api/chart-data.php -->
<?php
header('Content-Type: application/json');
$pdo = new PDO(...);
$stmt = $pdo->query("SELECT city_name, COUNT(*) as cnt FROM city GROUP BY city_name");
$data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); // [city => count]
echo json_encode(['labels' => array_keys($data), 'values' => array_values($data)]);

<!-- 前端 Vue + Chart.js -->
<script setup>
import { ref, onMounted } from 'vue';
import { Chart, ArcElement, Tooltip, Legend } from 'chart.js';
Chart.register(ArcElement, Tooltip, Legend);
const chart = ref(null);
onMounted(async () => {
    const { labels, values } = await fetch('/api/chart-data.php').then(r => r.json());
    new Chart(chart.value, {
        type: 'pie',
        data: { labels, datasets: [{ data: values, backgroundColor: ['#FF6384','#36A2EB','#FFCE56','#4BC0C0','#9966FF','#FF9F40'] }] },
        options: { responsive: true, plugins: { legend: { position: 'right' } } }
    });
});
</script>
<template><canvas ref="chart"></canvas></template>

方案 B:伺服器端渲染 (SSR) - 靜態圖片/PDF/郵件/報表

需求:無 JavaScript 環境 (郵件、PDF、Open Graph 社群分享圖、爬蟲預覽)。

工具語言/引擎輸出格式特色
Node.js + Puppeteer/PlaywrightHeadless ChromePNG, PDF, JPEG完整支援 CSS/Canvas/SVG/動畫、最佳相容性
Python + Matplotlib/Plotly/KaleidoAgg/ORCAPNG, SVG, PDF科學繪圖標準、向量輸出完美
PHP + GD / ImagickC LibraryPNG, JPEG, GIF, WebPPHP 原生、無外部依賴、效能佳、功能較簡單 (無動畫、3D)
Go + go-echarts / uPlotGoPNG, SVG高併發、單一二進位部署
QuickChart.io (API)SaaSPNG, SVG, PDF免維運、URL 參數即時生成、免費額度大

PHP GD 繪製餅圖範例 (零依賴、生產可用)

<?php
// pie.php?data=10,20,30&labels=A,B,C
$values = array_map('intval', explode(',', $_GET['data'] ?? '1,1,1'));
$labels = explode(',', $_GET['labels'] ?? 'A,B,C');
$colors = ['#FF6384','#36A2EB','#FFCE56','#4BC0C0','#9966FF','#FF9F40','#C9CBCF'];

$sum = array_sum($values);
$w = $h = 400; $r = 150; $cx = $cy = 200;
$img = imagecreatetruecolor($w, $h);
$white = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $white);
imageantialias($img, true);

$start = -90; // 從頂部開始
foreach ($values as $i => $val) {
    $angle = 360 * $val / $sum;
    $color = imagecolorallocate($img, ...sscanf($colors[$i % count($colors)], "#%2x%2x%2x"));
    imagefilledarc($img, $cx, $cy, $r*2, $r*2, $start, $start + $angle, $color, IMG_ARC_PIE);
    $start += $angle;
}

// 圖例 (簡易繪製在右側)
$legendX = 320; $legendY = 50;
foreach ($values as $i => $val) {
    $color = imagecolorallocate($img, ...sscanf($colors[$i % count($colors)], "#%2x%2x%2x"));
    $textColor = imagecolorallocate($img, 0, 0, 0);
    imagefilledrectangle($img, $legendX, $legendY, $legendX+15, $legendY+15, $color);
    imagestring($img, 3, $legendX+20, $legendY, "{$labels[$i]}: " . round(100*$val/$sum) . "%", $textColor);
    $legendY += 25;
}

header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);

遷移決策樹

需要互動/動畫/即時更新? → 是 → 前端渲染 (Chart.js/ECharts/D3)
                                 ↓ 否
需求環境支援 JS?             → 否 → SSR 靜態圖片 (Puppeteer/GD/QuickChart)
                                 ↓ 是
SEO/社群分享需靜態圖?        → 是 → 雙軌:API + SSR 預渲染 (Next.js/Edge Functions)
                                 ↓ 否
純前端渲染即可

結語

PHP `libswf`/`Ming` 產生 SWF 是技術演進中的一個分支,隨著 Flash 終結、HTML5 Canvas/SVG/WebGL 成熟、**「資料與視覺分離」**已成共識。現代架構採用 **PHP 輸出 JSON → 前端聲明式圖表庫渲染**,兼顧效能、可維護性、無障礙、SEO、響應式與離線支援。若需靜態圖片,請使用 **Headless Chrome (Puppeteer)** 或 **QuickChart.io API**,避免在 PHP 中手繪 GD 圖形 (除非極簡場景)。

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