d3 基礎折線圖和餅圖

折線圖

折現圖可使用svg折線元素polyline來定義一組相連的直線段,可是更推薦使用d3.line()path元素組合使用,這樣更加靈活。html

  • d3.line()構造一個新的線生成器,使用默認的.x.y設置x,y訪問器函數。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="test-svg">
        </div>
    </body>
    <script src="https://d3js.org/d3.v5.js"></script>
    <script>
        window.onload = function() {

            // 數據
            var data = [{
                date: new Date(2019, 3, 24),
                value: 23.24
            }, {
                date: new Date(2019, 3, 25),
                value: 72.15
            }, {
                date: new Date(2019, 3, 26),
                value: 38.84
            }, {
                date: new Date(2019, 3, 27),
                value: 58.62
            }, {
                date: new Date(2019, 3, 30),
                value: 10.80
            }, {
                date: new Date(2019, 4, 1),
                value: 85.47
            }];
            
            var width = 800,
                height = 400,
                padding = {
                    top: 40,
                    right: 40,
                    bottom: 40,
                    left: 40
                };
            var colors = d3.schemeSet2;
            var svg = d3.select("#test-svg")
                .append('svg')
                .attr('width', width + 'px')
                .attr('height', height + 'px');

            // x軸:時間軸
            var xScale = d3.scaleTime()
                .domain(d3.extent(data, function(d) {
                    return d.date;
                }))
                .range([padding.left, width - padding.right]);
            var xAxis = d3.axisBottom()
                .scale(xScale)
                .tickSize(10);
            svg.append('g')
                .call(xAxis)
                .attr("transform", "translate(0," + (height - padding.bottom) + ")")
                .selectAll("text")
                .attr("font-size", "10px")
                .attr("dx", "50px");

            // y軸
            var yScale = d3.scaleLinear()
                .domain([0, d3.max(data, function(d) {
                    return d.value;
                })])
                .range([height - padding.bottom, padding.top]);
            var yAxis = d3.axisLeft()
                .scale(yScale)
                .ticks(10);
            svg.append('g')
                .call(yAxis)
                .attr("transform", "translate(" + padding.left + ",0)");

            var line = d3.line()
                .x(function(d) {
                    return xScale(d.date);
                })
                .y(function(d) {
                    return yScale(d.value);
                });

            // 生成折線
            svg.append("path")
                .datum(data)
                .attr("fill", "none")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1.5)
                .attr("stroke-linejoin", "round")
                .attr("stroke-linecap", "round")
                .attr("d", line);
        }
    </script>

</html>

stroke-linecap

  • 路徑兩端的形狀。app

  • 屬性值:butt | round | square | inheritdom

stroke-linejoin

  • 路徑的轉角處使用的形狀svg

  • 屬性值:miter | round | bevel | inherit函數

餅圖

  • 餅圖通常使用餅佈局d3.pie()和弧線生成器d3.arc()來繪製。

餅佈局d3.pie()

// 生成餅佈局
            var pie = d3.pie().value(function(d) {
                return d.value;
            })(data);
  • startAngle:弧起始角度(角度跨度默認爲2π ≈6.283185307179586)佈局

  • endAngle:弧結束角度搜索引擎

  • padAngle:弧之間的間隔code

  • value:數值orm

弧線生成器d3.arc()

通常來講有四種狀況:視頻

1) 圓形:內圓半徑爲0,外圓半徑大於0,且圓的弧度大於等於2π。會生成一個之外圓半徑爲半徑的圓

2) 扇形:內圓半徑爲0,外圓半徑大於0,且圓的弧度小於2π。會生成一個之外圓半徑爲半徑的扇形

3) 環形:內圓半徑大於0,外圓半徑大於0,且圓的弧度大於等於2π。會生成一個環形

4) 環形扇區:內圓半徑大於0,外圓半徑大於0,且圓的弧度小於2π。會生成一個環形扇區

圓形餅圖

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="test-svg">
        </div>
    </body>
    <script src="https://d3js.org/d3.v5.js"></script>
    <script>
        window.onload = function() {

            // 數據
            var data = [{
                value: 335,
                name: '直接訪問'
            }, {
                value: 310,
                name: '郵件營銷'
            }, {
                value: 234,
                name: '聯盟廣告'
            }, {
                value: 135,
                name: '視頻廣告'
            }, {
                value: 1548,
                name: '搜索引擎'
            }];
            var width = 400,
                height = 400,
                padding = {
                    top: 40,
                    right: 40,
                    bottom: 40,
                    left: 40
                };
                
            var colors = d3.schemeSet2;
            var svg = d3.select("#test-svg")
                .append('svg')
                .attr('width', (width * 2) + 'px')
                .attr('height', (height * 2) + 'px');
                
            // 生成餅佈局
            var pie = d3.pie().value(function(d) {
                return d.value;
            })(data);

            var radius = Math.min(width, height);
            
            /*
             * 弧線生成器
             * .innerRadius 內圓半徑
             * .outerRadius 外圓半徑
             * .centroid 計算弧的中心
             */
            var arc = d3.arc()
                .innerRadius(0)
                .outerRadius(radius / 2);
            
            // 一個更大的圓弧,用來獲取標註線外圈的座標
            var outArc = d3.arc()
                .innerRadius(radius / 2)
                .outerRadius(radius);
                
            var line = d3.line()
                .x(function(d) {
                    return d[0];
                })
                .y(function(d) {
                    return d[1];
                });
            
            // 獲取標註線的點數據
            var getLabelLine = function(d, type) {
                var startPos = d.startAngle + (d.endAngle - d.startAngle) / 2;
                var data = [];
                var ra = (type === "text") ? 2.5 : 1;
                data.push(arc.centroid(d));
                data.push(outArc.centroid(d));
                data.push({
                    0: outArc.centroid(d)[0] + (40 * (startPos < Math.PI ? 1 : -ra)),
                    1: outArc.centroid(d)[1]
                });

                return data;
            }
            
            var containers = svg.append("g")
                .attr("transform", "translate(" + height + "," + height + ")");
                
            var container = containers.selectAll("g")
                .data(pie)
                .join("g");
            
            // 繪製餅圖
            container.append("path")
                .attr("stroke", "white")
                .attr("d", arc)
                .attr("fill", function(d, i) {
                    return colors[i];
                });
            
            // 繪製標註線
            container.append("path")
                .datum(function(d) {
                    return getLabelLine(d, "path");
                })
                .attr("class", "tips")
                .attr("fill", "none")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1)
                .attr("stroke-linejoin", "round")
                .attr("stroke-linecap", "round")
                .attr("d", line);
            
            // 繪製標註線上文字
            container.append("text")
                .datum(function(d) {
                    d.pos = getLabelLine(d, "text")[2];
                    return d;
                })
                .text(function(d) {
                    return d.data.name;
                })
                .attr("dx", function(d) {
                    return d.pos[0]
                })
                .attr("dy", function(d) {
                    return d.pos[1]
                });
        }
    </script>

</html>

扇形餅圖

var pie = d3.pie().startAngle(0).endAngle(Math.PI).value(function(d) {
                return d.value;
            })(data);

            var radius = Math.min(width, height);
            
            var arc = d3.arc()
                .innerRadius(0)
                .outerRadius(radius / 2);

環形餅圖

var pie = d3.pie().value(function(d) {
                return d.value;
            })(data);

            var radius = Math.min(width, height);
            
            var arc = d3.arc()
                .innerRadius(radius / 4)
                .outerRadius(radius / 2);

環形扇區餅圖

var pie = d3.pie().startAngle(0).endAngle(Math.PI).value(function(d) {
                return d.value;
            })(data);

            var radius = Math.min(width, height);
            
            var arc = d3.arc()
                .innerRadius(radius / 4)
                .outerRadius(radius / 2);

相關文章
相關標籤/搜索