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
  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值