D3 - 绘制散点图

D3绘制散点图

效果图
在这里插入图片描述
数据来自:https://www.worldbank.org/

完整代码(不含Initialize初始化数据的函数):

<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.9;
    let T = new Array();
    let NAME = new Array();
    let RANGE = new Array();
    let Data = new Array();
    // [1] -> population of age range 0~14
    // [2] -> population of age range 15~64
    // [3] -> population of age range 65+

    initialize();
    //初始化数据

    // 内部空间
    let inner = {top: 50, right: 50, bottom: 50, left: 50};

    // 坐标轴的定义
    let xScale = d3.scaleLinear()
        .domain([1960, 2018])
        .range([0, w - inner.left - inner.right])
        .nice();

    let xAxis = d3.axisBottom(xScale);

    let yScale = d3.scaleLinear()
        .domain([0, 100])
        .range([h - inner.top - inner.bottom, 0])
        .nice();

    let yAxis = d3.axisLeft(yScale);

    let svg = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h)
        .append("g");

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

    svg.append("g")
        .attr("transform", "translate(" + inner.left + "," + (inner.top) + ")")
        .call(yAxis);


    // 重画某一条线上的数据
    function F(v, t) {
        svg.append("g")
            .selectAll("circle")
            .data(Data[t])
            .enter()
            .append("circle")
            .attr("fill", function (d) {
                if (d[0] === v) return T[d[0] - 1];
            })
            .attr("cx", function (d) {
                if (d[0] === v) return inner.left + xScale(d[1]);
            })
            .attr("cy", function (d) {
                if (d[0] === v) return inner.top + yScale(d[2]);
            })
            .attr("r", 2);
    }

    // 根据点击次数处理效果
    function FF(v) {
        svg.selectAll("circle").remove();

        for (let k = 1; k <= 3; ++k) {
            for (let i = 1; i <= 13; ++i) {
                if (cnt[i] > 0 && cnt[i] % 2 === 1) {
                    if (ct[k] > 0 && ct[k] % 2 === 1) {
                        F(i, k);
                    }
                }
            }
        }
    }

    // 定义可选的国家的方块
    let svg2 = d3.select("body")
        .append("svg")
        .attr("width", 500)
        .attr("height", 500);

    let cnt = new Array();
    let ct = new Array();
    for (i = 1; i <= 13; ++i) {
        cnt[i] = 0;
    }
    for (i = 1; i <= 3; ++i) ct[i] = 0;

    svg2.selectAll("rect")
        .data(NAME)
        .enter()
        .append("rect")
        .attr("y", function (d, i) {
            return i * 20;
        })
        .attr("x", function (d) {
            return 20;
        })
        .attr("width", 20)
        .attr("height", 20)
        .attr("fill", function (d, i) {
            return T[i];
        })
        .on("click", function (d, i) {
            cnt[i + 1]++;
            FF();
        });

    svg2.selectAll("text")
        .data(NAME)
        .enter()
        .append("text")
        .attr("transform", function (d, i) {
            return "translate(" + (40) + "," + (i * 20 + 15) + ")";
        })
        .attr("fill", 'black')
        .attr("font-size", 10)
        .text(function (d, i) {
            return NAME[i];
        });


    // 定义选择的数据种类的方块
    let svg3 = d3.select("body")
        .append("svg")
        .attr("width", 500)
        .attr("height", 500);

    svg3.selectAll("rect")
        .data(RANGE)
        .enter()
        .append("rect")
        .attr("y", function (d, i) {
            return 20;
        })
        .attr("x", function (d, i) {
            return 40 * i + 5;
        })
        .attr("width", 20)
        .attr("height", 20)
        .attr("fill", "red")
        .on("click", function (d, i) {
            ct[i + 1]++;
            FF();
        });

    svg3.selectAll("text")
        .data(RANGE)
        .enter()
        .append("text")
        .attr("text-anchor", "middle")
        .attr("transform", function (d, i) {
            return "translate(" + (i * 40 + 15) + "," + (60) + ")";
        })
        .attr("fill", 'black')
        .attr("font-size", 10)
        .text(function (d, i) {
            return RANGE[i];
        });
</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.9;

获得网页页面上的可视区域。

    // 坐标轴的定义
    let xScale = d3.scaleLinear()
        .domain([1960, 2018])
        .range([0, w - inner.left - inner.right])
        .nice();

    let xAxis = d3.axisBottom(xScale);

    let yScale = d3.scaleLinear()
        .domain([0, 100])
        .range([h - inner.top - inner.bottom, 0])
        .nice();

    let yAxis = d3.axisLeft(yScale);

domain即值域,表示数据的范围。其中的数据可以是一个区间,也可以是一个数组,可以是离散的数据。
range即映射范围,设置刻度的输出范围值的指定数组。
nice修改规模域,使边界延伸到最近的整数值。

    // 重画某一条线上的数据
    function F(v, t) {
        svg.append("g")
            .selectAll("circle")
            .data(Data[t])
            .enter()
            .append("circle")
            .attr("fill", function (d) {
                if (d[0] === v) return T[d[0] - 1];
            })
            .attr("cx", function (d) {
                if (d[0] === v) return inner.left + xScale(d[1]);
            })
            .attr("cy", function (d) {
                if (d[0] === v) return inner.top + yScale(d[2]);
            })
            .attr("r", 2);
    }

以圆圈的形式绘制散点图。cx,cy表示坐标位置。r表示半径大小。
借助匿名函数来选择满足要求。

后面额外添加了两个画布,一个用来表示每个国家对应的颜色。颜色用矩形的形式呈现,后面添加文本。

    svg2.selectAll("rect")
        .data(NAME)
        .enter()
        .append("rect")
        .attr("y", function (d, i) {
            return i * 20;
        })
        .attr("x", function (d) {
            return 20;
        })
        .attr("width", 20)
        .attr("height", 20)
        .attr("fill", function (d, i) {
            return T[i];
        })
        .on("click", function (d, i) {
            cnt[i + 1]++;
            FF();
        });

矩形设置了点击的事件处理,即点击该矩形后显示该国家的数据。

同时增添了一个svg3,用来选择呈现哪一部分的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值