D3 - 動態條形圖製作

數據來自csv文件。
繪製效果圖:

在這裏插入圖片描述
數據集解釋:數據信息爲美國六個主要城市每個月的光照時間變化。

代碼詳細解釋:

let Color = new Array();

    // 隨機生成每個城市的代表顏色
    for (let i = 0; i < 6; ++i) {
        Color[i] = 'rgba(' + Math.random() * 255 + ',' + Math.random() * 255 + ',' + Math.random() * 255 + ',' + 0.8 + ')';
    }

首先生成所有城市的顏色。所有顏色的rgb數值均隨機生成。

 // 構造比例尺
    xScale = d3.scaleLinear()
        .domain([0, 350])
        .range([0, w - inner.left - inner.right])
        .nice();

    xAxis = d3.axisBottom(xScale);

    svg.append("g")
        .attr("transform", "translate(" + inner.left + "," + (h - inner.bottom - 40) + ")")
        .call(xAxis);

構造下方的比例尺。將比例尺平放放在底部。

// 解析csv數據
    d3.csv("sunshine.csv").then(function (d) {
        Data = d;
        // 首先按月份排序
        Data.sort(function (a, b) {
            return a.monthnum - b.monthnum;
        });
        console.log(Data);
        draw();
    });

解析csv數據。注意這個過程是異步的,接下來所進行的所有操作均在draw函數中執行。

//右下方數值,表示月份
        let comment = svg.append("text")
            .attr("x", w - inner.right - inner.right)
            .attr("y", h - inner.bottom - inner.bottom - 40)
            .attr("fill", "black")
            .text(function () {
                return Data[idx].month;
            })
            .style("font-size", "40");

添加右下角的文本數據,表示當前狀態所示的月份。

// 綁定該年的數據
        const groups = svg.selectAll("g")
            .data(DataEntry).enter()
            .append("g");

        // 生成標籤和矩形
        let labels = groups.data(DataEntry)
            .enter().append("text")
            .text(d => d.city)
            .attr("x", function (d, i) {
                return inner.left - 10;
            })
            .style("font-size", 20)
            .attr("text-anchor", "end");

        let rects = groups.data(DataEntry)
            .enter().append("rect")
            .attr("x", inner.left)
            .attr("height", H * 0.65)
            .attr("fill", function (d, i) {
                return Color[i];
            })
            .attr("width", function (d) {
                return xScale(d.sunshine);
            });

數據主體部分,即表示數據的直方圖以及數據旁邊的城市名稱。注意利用text-anchor來控制文本的對齊信息。此處爲右對齊。

// 設定更新函數
        function UpdateElement() {

            // 通過data指定綁定的鍵值
            labels.data(DataEntry, d => d.city)
                .transition()
                .duration(600)
                .attr("y", function (d, i) {
                    return i * H + inner.bottom + 40;
                });

            rects.data(DataEntry, d => d.city)
                .transition()
                .duration(600)
                .attr("y", function (d, i) {
                    return i * H + inner.bottom;
                })
                .attr("width", function (d) {
                    return xScale(d.sunshine);
                });
        }

設定更新函數。
這裏一定要注意,利用data來綁定更新數據,d => d.city爲設置的綁定的鍵值。否則綁定其他信息會導致結果出錯。

// 更新函數
        function update(t) {
            let W = new Array();
            for (let i = 0; i < 6; ++i)
                W.push(Data[t * 6 + i]);
            W.sort(function (a, b) {
                return b.sunshine - a.sunshine;
            });
            DataEntry = W;
            comment.text(DataEntry[0].month);
            UpdateElement();
        }

        // 調用更新函數,每0.7s更新一次
        setInterval(function () {
            update((++idx) % 12);
        }, 700);

設置更新函數以及調用更新函數。

完整代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>7</title>
</head>
<body>
<script src="https://d3js.org/d3.v5.js"></script>
<script>

    let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    w *= 0.98;
    h *= 0.90;

    let inner = {top: 100, right: 100, bottom: 50, left: 200};
    let xScale, xAxis;
    let DataEntry = new Array();
    let Data = new Array();
    let H = (h - inner.bottom - inner.top) / 6 * 0.95;
    let Color = new Array();

    // 隨機生成每個城市的代表顏色
    for (let i = 0; i < 6; ++i) {
        Color[i] = 'rgba(' + Math.random() * 255 + ',' + Math.random() * 255 + ',' + Math.random() * 255 + ',' + 0.8 + ')';
    }

    // 添加畫布
    let svg = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h)
        .append("g");

    // 構造比例尺
    xScale = d3.scaleLinear()
        .domain([0, 350])
        .range([0, w - inner.left - inner.right])
        .nice();

    xAxis = d3.axisBottom(xScale);

    svg.append("g")
        .attr("transform", "translate(" + inner.left + "," + (h - inner.bottom - 40) + ")")
        .call(xAxis);

    // 月份循環變量
    let idx = 0;

    // 解析csv數據
    d3.csv("sunshine.csv").then(function (d) {
        Data = d;
        // 首先按月份排序
        Data.sort(function (a, b) {
            return a.monthnum - b.monthnum;
        });
        console.log(Data);
        draw();
    });

    function draw() {

        //右下方數值,表示月份
        let comment = svg.append("text")
            .attr("x", w - inner.right - inner.right)
            .attr("y", h - inner.bottom - inner.bottom - 40)
            .attr("fill", "black")
            .text(function () {
                return Data[idx].month;
            })
            .style("font-size", "40");

        // 添加該月份的所有的城市信息
        for (let i = 0; i < 6; ++i)
            DataEntry.push(Data[idx * 6 + i]);
        DataEntry.sort(function (a, b) {
            return b.sunshine - a.sunshine;
        });
        // console.log(DataEntry);

        // 綁定該年的數據
        const groups = svg.selectAll("g")
            .data(DataEntry).enter()
            .append("g");

        // 生成標籤和矩形
        let labels = groups.data(DataEntry)
            .enter().append("text")
            .text(d => d.city)
            .attr("x", function (d, i) {
                return inner.left - 10;
            })
            .style("font-size", 20)
            .attr("text-anchor", "end");

        let rects = groups.data(DataEntry)
            .enter().append("rect")
            .attr("x", inner.left)
            .attr("height", H * 0.65)
            .attr("fill", function (d, i) {
                return Color[i];
            })
            .attr("width", function (d) {
                return xScale(d.sunshine);
            });

        // 設定更新函數
        function UpdateElement() {

            // 通過data指定綁定的鍵值
            labels.data(DataEntry, d => d.city)
                .transition()
                .duration(600)
                .attr("y", function (d, i) {
                    return i * H + inner.bottom + 40;
                });

            rects.data(DataEntry, d => d.city)
                .transition()
                .duration(600)
                .attr("y", function (d, i) {
                    return i * H + inner.bottom;
                })
                .attr("width", function (d) {
                    return xScale(d.sunshine);
                });
        }

        UpdateElement();

        // 更新函數
        function update(t) {
            let W = new Array();
            for (let i = 0; i < 6; ++i)
                W.push(Data[t * 6 + i]);
            W.sort(function (a, b) {
                return b.sunshine - a.sunshine;
            });
            DataEntry = W;
            comment.text(DataEntry[0].month);
            UpdateElement();
        }

        // 調用更新函數,每0.7s更新一次
        setInterval(function () {
            update((++idx) % 12);
        }, 700);
    }

    svg.append("text")
        .text("Monthly Hours of Sunshine")
        .attr("x", w / 2)
        .attr("y", 30)
        .style("font-size", 25)
        .attr("text-anchor", "middle");

</script>
</body>
</html>

另附sunshine.csv中的數據

city,lon,lat,month,monthnum,sunshine
Seattle,-122.335167,47.608013,Jan,0,69
Seattle,-122.335167,47.608013,Feb,1,108
Seattle,-122.335167,47.608013,Mar,2,178
Seattle,-122.335167,47.608013,Apr,3,207
Seattle,-122.335167,47.608013,May,4,253
Seattle,-122.335167,47.608013,Jun,5,268
Seattle,-122.335167,47.608013,Jul,6,312
Seattle,-122.335167,47.608013,Aug,7,281
Seattle,-122.335167,47.608013,Sep,8,221
Seattle,-122.335167,47.608013,Oct,9,142
Seattle,-122.335167,47.608013,Nov,10,72
Seattle,-122.335167,47.608013,Dec,11,52
Chicago,-87.623177,41.881832,Jan,0,135
Chicago,-87.623177,41.881832,Feb,1,136
Chicago,-87.623177,41.881832,Mar,2,187
Chicago,-87.623177,41.881832,Apr,3,215
Chicago,-87.623177,41.881832,May,4,281
Chicago,-87.623177,41.881832,Jun,5,311
Chicago,-87.623177,41.881832,Jul,6,318
Chicago,-87.623177,41.881832,Aug,7,283
Chicago,-87.623177,41.881832,Sep,8,226
Chicago,-87.623177,41.881832,Oct,9,193
Chicago,-87.623177,41.881832,Nov,10,113
Chicago,-87.623177,41.881832,Dec,11,106
New York,-73.935242,40.73061,Jan,0,154
New York,-73.935242,40.73061,Feb,1,171
New York,-73.935242,40.73061,Mar,2,213
New York,-73.935242,40.73061,Apr,3,237
New York,-73.935242,40.73061,May,4,268
New York,-73.935242,40.73061,Jun,5,289
New York,-73.935242,40.73061,Jul,6,302
New York,-73.935242,40.73061,Aug,7,271
New York,-73.935242,40.73061,Sep,8,235
New York,-73.935242,40.73061,Oct,9,213
New York,-73.935242,40.73061,Nov,10,169
New York,-73.935242,40.73061,Dec,11,155
San Francisco,-122.446747,37.733795,Jan,0,165
San Francisco,-122.446747,37.733795,Feb,1,182
San Francisco,-122.446747,37.733795,Mar,2,251
San Francisco,-122.446747,37.733795,Apr,3,281
San Francisco,-122.446747,37.733795,May,4,314
San Francisco,-122.446747,37.733795,Jun,5,330
San Francisco,-122.446747,37.733795,Jul,6,300
San Francisco,-122.446747,37.733795,Aug,7,272
San Francisco,-122.446747,37.733795,Sep,8,267
San Francisco,-122.446747,37.733795,Oct,9,243
San Francisco,-122.446747,37.733795,Nov,10,189
San Francisco,-122.446747,37.733795,Dec,11,156
Houston,-95.358421,29.749907,Jan,0,144
Houston,-95.358421,29.749907,Feb,1,141
Houston,-95.358421,29.749907,Mar,2,193
Houston,-95.358421,29.749907,Apr,3,212
Houston,-95.358421,29.749907,May,4,266
Houston,-95.358421,29.749907,Jun,5,298
Houston,-95.358421,29.749907,Jul,6,294
Houston,-95.358421,29.749907,Aug,7,281
Houston,-95.358421,29.749907,Sep,8,238
Houston,-95.358421,29.749907,Oct,9,239
Houston,-95.358421,29.749907,Nov,10,181
Houston,-95.358421,29.749907,Dec,11,146
Miami,-80.191788,25.761681,Jan,0,222
Miami,-80.191788,25.761681,Feb,1,227
Miami,-80.191788,25.761681,Mar,2,266
Miami,-80.191788,25.761681,Apr,3,275
Miami,-80.191788,25.761681,May,4,280
Miami,-80.191788,25.761681,Jun,5,251
Miami,-80.191788,25.761681,Jul,6,267
Miami,-80.191788,25.761681,Aug,7,263
Miami,-80.191788,25.761681,Sep,8,216
Miami,-80.191788,25.761681,Oct,9,215
Miami,-80.191788,25.761681,Nov,10,212
Miami,-80.191788,25.761681,Dec,11,209
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章