【d3.js入门】基本散点图动画

945 阅读2分钟

前面写了一篇 【d3.js入门】 基本散点图,这次我们在这个面积图基础上添加一些动画效果。

散点图.gif

好,废话多说,我们继续绘制换一个散点图。

首先,我们创建一个 div 元素,并将其添加到 body 里:

let dom = document.createElement('div');
document.body.appendChild(dom);

接下来,生成一些随机的数据,并设置画布和轴的配置信息:

let dataset = [];
for (let i = 0; i < 30; i++) {
    let x = Math.random();
    let y = Math.floor(Math.random() * 90 + 10);
    dataset.push([x, y]);
}

let padding = 30;
let svgWidth = 600;
let svgHeight = 400;

let xScale = d3.scaleLinear()
    .domain([0, 1])
    .range([padding, svgWidth - padding]);

let yScale = d3.scaleLinear()
    .domain([0, 100])
    .range([svgHeight - padding, padding]);

然后,创建 svg 元素,并设置它的宽度、高度和边框样式:

let svg = d3.select(dom)
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .style('border', '1px solid #999999');

接下来,为每个数据点绘制圆点,设置其属性包括半径大小、填充颜色以及位置等,并使用 selectAll()data()enter() 方法将数据绑定到元素上:

let dots = svg.selectAll(".dot")
    .data(dataset)
    .enter().append("circle")
    .attr("class", "dot")
    .attr("r", 5)
    .attr("fill", "#69b3a2")
    .attr("cx", function (d) { return xScale(d[0]); })
    .attr("cy", function (d) { return yScale(d[1]); });

最后,创建坐标轴并添加到 svg 元素上:

let xAxis = d3.axisBottom(xScale);
let yAxis = d3.axisLeft(yScale);

svg.append("g")
    .attr("class", "x-axis")
    .attr("transform", "translate(0," + (svgHeight - padding) + ")")
    .call(xAxis);

svg.append("g")
    .attr("class", "y-axis")
    .attr("transform", "translate(" + padding + ",0)")
    .call(yAxis);

添加了交互功能,包括更新数据、添加数据和删除数据。具体步骤如下:

首先,创建一组按钮,并将它们添加到画布的下方。为每个按钮设置一个 onclick 事件监听器:

let innerHtml = ['更新数据', '添加数据', '删除数据'];
let buts = [];
let butdiv = document.createElement('div');
dom.appendChild(butdiv);

innerHtml.map(item => {
    let but = document.createElement('button');
    but.innerHTML = item;
    butdiv.appendChild(but);
    buts.push(but);
})

// 更新数据
buts[0].onclick = function () {
    dataset.forEach(item => {
        item[0] = Math.random();
        item[1] = Math.floor(Math.random() * 90 + 10);
    })

    dots = svg.selectAll(".dot")
        .data(dataset)
        .transition()
        .duration(1000)
        .attr("cx", function (d) { return xScale(d[0]); })
        .attr("cy", function (d) { return yScale(d[1]); });
}

// 添加数据
buts[1].onclick = function () {
    let x = Math.random();
    let y = Math.floor(Math.random() * 90 + 10);
    dataset.push([x, y]);
    dots = svg.selectAll(".dot")
        .data(dataset)
        .enter().append("circle")
        .attr("class", "dot")
        .attr("r", 20)
        .attr("opacity", 0)
        .attr("fill", "#69b3a2")
        .attr("cx", function (d) { return xScale(d[0]); })
        .attr("cy", function (d) { return yScale(d[1]); })
        .transition()
        .duration(1000)
        .attr("r", 5)
        .attr("opacity", 1)
}

// 删除数据
buts[2].onclick = function () {
    dataset.pop();
    dots = svg.selectAll(".dot")
        .data(dataset)
        .exit()
        .transition()
        .duration(1000)
        .attr("r", 20)
        .attr("opacity", 0)
        .remove()
}

更新数据的功能将数组中的每个元素都重新赋予新的随机值,然后使用 selectAll()data()transition() 方法来更新圆点的位置。

添加数据的功能会向数组中添加一个新元素,并通过 selectAll()data()enter()append() 方法来将新的圆点添加到可视化中。在此之前,先将圆点半径设置为 20 并且不透明度为零,然后在过渡期间,将其半径缩小至 5 并且逐渐变得不透明。

删除数据的功能会从数组末尾删除一个元素,并使用 selectAll()data()exit()transition() 方法来移除可视化中对应的圆点。在此之前,将这些圆点的半径设置为 20 并且不透明度为零,然后在过渡期间,将其半径放大至 20 并且逐渐变得不可见,最终移除它们。

在线演示和源码地址:scqilin.github.io/d3js/basic-…