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

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

ainpie.gif

我们继续绘制D3.js饼图

绘制饼图

首先,定义饼图的数据集,包括每个区块的名称和数值:

let dataset = [
    { name: "春", value: 20 },
    { name: "夏", value: 50 },
    { name: "秋", value: 20 },
    { name: "冬", value: 80 }
];

然后,设置饼图的颜色集合,其中 scaleOrdinal 方法用于生成一个颜色比例尺,输入参数是一个数组,每个元素对应一个颜色:

let color = d3.scaleOrdinal([
    "#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3",
    "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3",
    "#8dd3c7", "#ffffb3", "#bebada", "#fb8072",
    "#80b1d3", "#fdb462", "#b3de69", "#fccde5",
    "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f",
    "#1f78b4", "#33a02c", "#cab2d6", "#6a3d9a"
]);

接着,定义SVG容器的尺寸,并设置饼图半径:

let svgWidth = 600;
let svgHeight = 400;

let radius = Math.min(svgWidth, svgHeight) / 3;

接下来,创建一个弧生成器。d3.arc() 用于创建圆弧生成器, .innerRadius().outerRadius() 方法分别用于设置内半径和外半径。

let arcGenerator = d3.arc()
    .innerRadius(radius * 0.5)
    .outerRadius(radius);

然后,创建一个布局,也就是将数据转化为可绘制饼图的数据格式,使用 d3.pie() 方法即可。注意 value 函数返回每个部分所占比例。

let pieLayout = d3.pie()
    .sort(null)
    .value(function (d) {
        return d.value;
    });

接下来,生成最终的饼图数据,使用 .join() 方法将新数据绑定到选择集上,返回更新后的选择集。这里使用 pieLayout() 方法将原始数据转换为可用于 d3.arc() 的格式。

let pieData = pieLayout(dataset);

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

let pieContainer = svg.append("g")
    .attr("transform", "translate(" + svgWidth / 2 + "," + svgHeight / 2 + ")");

let piePaths = pieContainer.selectAll(".arc")
    .data(pieData)
    .join("path")
    .attr("class", "arc")
    .attr("d", arcGenerator)
    .attr("fill", function (d, i) {
        return color(i);
    })
    .each(function (d) {
        this._current = d;
    });

到目前为止,基本的饼图已经绘制完成了,然后我开始添加动画。
在之前的基础上,我们现在向代码中添加了一些交互元素,如更新数据、正向排序、反向排序、添加数据、删除数据等功能。这些按钮可以帮助用户进行数据与图表的交互操作。

首先,使用 innerHTML 设置按钮文字:

let innerHtml = ['更新数据', '正向排序', '反向排序', '添加数据', '删除数据'];

然后,创建一个空数组 buts 和一个 <div> 元素,在其中遍历 innerHtml 数组,生成相应的按钮,并将它们添加到 <div> 元素中和 buts 数组中:

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.value = Math.random() * 90 | 0 + 10;
    });

    pieLayout.sort(null);
    // 生成新的饼图数据
    pieData = pieLayout(dataset);
    // 计算过渡状态的函数
    let arcTween = function (d, i) {
        let interpolate = d3.interpolate(this._current, pieData[i]);
        this._current = interpolate(0);
        return function (t) {
            return arcGenerator(interpolate(t));
        };
    };

    // 更新饼图数据
    piePaths = pieContainer.selectAll(".arc")
        .data(pieData)
        .join("path")
        .attr("class", "arc")
        .attr("d", arcGenerator)
        .attr("fill", function (d, i) {
            return color(i);
        });

    // 添加过渡动画
    piePaths.transition()
        .duration(1000)
        .attrTween("d", arcTween);

    // 更新图例 texts
    addLegend();
};

其他功能的实现与此类似,不再一一解释。

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYpu7IYw' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片