找回密碼
 註冊
搜索
查看: 241|回復: 0

以JavaScript , SVG 繪製一個 pieChart (圓餅圖)

[複製鏈接]
發表於 5 天前 | 顯示全部樓層 |閱讀模式
Push to Facebook
展示圖:

JavaScript SVG 繪製 pieChart 圓餅圖

JavaScript  SVG 繪製  pieChart  圓餅圖



程式碼
  1. <div id="chart"></div>

  2. <script>
  3.     /**
  4.      * 建立SVG元素,並繪製一個圓餅圖
  5.      * width, height: 此SVG圖形大小,單位是像素(pixels)
  6.      * cx, cy, r : 此圓餅中心和半徑
  7.      * lx, ly : piechart的左上角
  8.      * data : 一個物件,其特性名稱是資料標籤(data labels), 而特性值是每個標籤關聯的值
  9.      *
  10.      * 此函式迴船SVG元素,呼叫者必須把她插入到文件中,使他變得可見
  11.      */
  12.     function pieChart(options) {
  13.         let {width, height, cx, cy, r, lx, ly, data} = options;
  14.         // svg元素的XML命名空間
  15.         let svg = "http://www.w3.org/2000/svg";
  16.         //創建SVG元素,並指出像素大小與使用者座標
  17.         let chart = document.createElementNS(svg, "svg");
  18.         chart.setAttribute("width", width);
  19.         chart.setAttribute("height", height);
  20.         chart.setAttribute("viewBox", `0 0 ${width} ${height}`);
  21.         //定義文字樣式
  22.         chart.setAttribute("font-family", "sans-serif");
  23.         chart.setAttribute("font-size", "18")

  24.         //以陣列方式取得那些標籤和值,並加總那些值
  25.         //以知道這圓餅有多大
  26.         let labels = Object.keys(data);
  27.         let values = Object.values(data);
  28.         let total = values.reduce((x,y) => x+y);

  29.         //為所有切片找出角度。切片i起始於angles[i]
  30.         //結束於angles[i+1]。弧度(radians)
  31.         let angles = [0];
  32.         values.forEach((x,i) => angles.push(angles[i] + x/total * 2 * Math.PI));

  33.         // 現在以迴圈跑過此圓餅的切片
  34.         values.forEach((value, i) => {
  35.             //計算切片與圓相交的兩點位置
  36.            let x1 = cx + r * Math.sin(angles[i]);
  37.            let y1 = cy - r * Math.cos(angles[i]);
  38.            let x2 = cx + r * Math.sin(angles[i+1]);
  39.            let y2 = cy - r * Math.cos(angles[i+1]);

  40.            let big = (angles[i+1] - angles[i] > Math.PI) ? 1 : 0;
  41.            
  42.            // 此字串描述如何繪製圓餅圖的一個切片
  43.            let path = `M${cx},${cy}` + `L${x1},${y1}` + `A${r},${r} 0 ${big} 1` + `${x2},${y2}` + "Z";
  44.            // 大約15個顏色
  45.            let color = `hsl(${(i*40)%360},${90-3*i}%,${50+2*i}%)`;
  46.            let slice = document.createElementNS(svg , "path");
  47.            slice.setAttribute("d", path);
  48.            slice.setAttribute("fill", color);
  49.            slice.setAttribute("stroke", "black");
  50.            slice.setAttribute("stroke-width", "1");
  51.            chart.append(slice);
  52.             
  53.            //繪製為該值一個對應小方形
  54.            let icon = document.createElementNS(svg, "rect");
  55.            icon.setAttribute("x", lx);
  56.            icon.setAttribute("y", ly+30*i);
  57.            icon.setAttribute("width", 20);
  58.            icon.setAttribute("height", 20);
  59.            icon.setAttribute("fill", color);
  60.            icon.setAttribute("stroke", "black");
  61.            icon.setAttribute("stroke-width", "1");
  62.            chart.append(icon);
  63.             
  64.            //新增標籤到小方形右邊
  65.            let label = document.createElementNS(svg, "text");
  66.            label.setAttribute("x", lx + 30);
  67.            label.setAttribute("y", ly +30*i +16);
  68.            label.append(`${labels[i]} ${value}`);
  69.            chart.append(label);
  70.         });
  71.         return chart;
  72.     }

  73.     document.querySelector("#chart").append(pieChart({
  74.         width:640, height: 400, cx:200, cy:200, r:180, lx:400, ly:10,
  75.         data:{
  76.             "JavaScript" : 71.5,
  77.             "Java": 45.4,
  78.             "Bash/Shell": 40.4,
  79.             "Python" : 37.9,
  80.             "C#" : 35.3,
  81.             "PHP" : 31.4,
  82.             "C++" : 24.6,
  83.             "C" : 22.1,
  84.             "TypeScript" : 18.3,
  85.             "Ruby" : 10.3,
  86.             "Swift" : 8.3,
  87.             "Obiective-C" : 7.3,
  88.             "Go" : 7.2,
  89.         }
  90.     }));

  91. </script>
複製代碼


您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

Archiver|手機版|小黑屋|TShopping

GMT+8, 2025-5-24 19:32 , Processed in 0.024864 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回復 返回頂部 返回列表