d3.js 布局(layout)是什么

4,257 阅读4分钟

前言

通过之前的学习实践了一阵子d3,但是很多效果实现都是照着demo改改下来的,没有自己一套完整的步骤。在经过更多地了解与学习之后,终于略知一二,其中最大关系的就是d3的布局(layout)。

d3.js绘图步骤

d3的绘图步骤相比Echarts等开箱即用的框架复杂得多,这里拿来一张很棒的图(来源为十二月咖啡馆,链接于文末)

从中可以看到布局在其中起着关键的一步。

布局到底是什么?

那么d3中什么是布局呢?跟CSS一样吗????
还有我们之前的柱状图怎么就不需要这玩意了?——>因为图形太简单。
回到正题,这里我参考了三个不同地方出处的理解:

十二月咖啡馆:布局的作用是:将不适合用于绘图的数据转换成了适合用于绘图的数据。

d3官方文档: Layout functions sets up and modifies data so that it can be rendered in different shapes. The layout functions don't do the drawing of the shapes.

Visualization on the Web Tutorials:Layouts make it easier to spatially arrange, shape and size elements representing data on the screen.

同时在实践之后,我添油加醋地给出了自己的理解:

布局(layout)是一个函数,将要可视化的数据data放入布局函数中,经过算法处理,返回方便d3绘图的数据。同时,布局函数并不直接参与绘图,只是告诉你绘图所用的关键信息

这么说可能还是有点晦涩,接下来我以一个demo说明

pie(饼图) demo

此demo学习了Visualization on the Web Tutorials的例子,链接置于文末,但是文中一个地方对d3函数链式返回理解有误。

说明大部分写在代码注释里,下一部分根据注释及解释进一步说明,完整代码点击这里

demo步骤说明

步骤1:确定svg

。没什么好说的,但是还是写在步骤里

<body>
    <svg class="pie-svg"></svg>
</body>

步骤2:假设数据及一些基础数值

也没什么好说的,注意的一点就是svg的transform与css的有不同
看看假设的数据data,马上用到

    /**
     * 假设数据
     */
    const data = [
        {
            name: 'A',
            percentage: 30
        },
        {
            name: 'B',
            percentage: 20
        },
        {
            name: 'C',
            percentage: 30
        },
        {
            name: 'D',
            percentage: 20
        }
    ];
    /**
     * 基础数值
     */
    const width = 800,
          height = 500,
          radius = Math.min(width, height)/2 - 10;
          console.log(radius);
    /**
     * 插入g容器
     */
   const g = d3.select('.pie-svg')
                 .attr('width', width)
                 .attr('height', height)
                 .append('g')
                 .attr('transform', `translate(${width/2}, ${height/2})`);//图形左上角相对画布偏移

步骤3:pie layout——用于返回适合绘图的数据

这里就是重点了!通过layout生成方便绘图的数据,先看代码👇

    /**
     * 定义layout generator(怎么翻译??布局发生器??),此例中即为变量pie
     */
    const pie = d3.pie();
    //告诉layout generator怎么处理要可视化的数据
    pie.value(function(d){
        return d.percentage;
    });
    //多数文章将布局理解为用于数据转换,我个人添油加醋一番认为如下: 
    //原数据 ————> layout generator ————> 便于可视化布局的数据
    const pieData = pie(data);
    console.log('pieData:', pieData);//原数据于pieData[i].data之中

截图pieData瞧瞧布局函数干了什么

如图,原来的data[i]置于pieData[i].data中,其他的属性比如startAngle、endAngele等等,就是方便绘图的数据了,那怎么使用呢?见下一步。

步骤4:arc generator——利用关键信息、绘图使用的工具

layout给了我们绘图的关键信息,arc generator就是利用这些关键信息的工具
arc generator可利用startAngle,endAngle这些属性绘制path元素的d属性来描绘路径。

    /**
     * 创建arc generator(此例中即为变量arc),通过pieData,生成path的d属性
     * 上述原理:arc通过pieData数组中每个元素对象的startAngle,endAngle进行计算(outerRadius与innerRadius在此例中设置了统一)
     * 流程图如下:
     * pieData[i]————>arc————>path元素d属性
     * 具体请看文档:https://github.com/d3/d3-shape/blob/v1.3.4/README.md#arc
     */
    const arc = d3.arc();
    arc.outerRadius(radius);
    arc.innerRadius(0);
    console.log(`举例:生成path的d属性:\n`,arc(pieData[0]));

瞧瞧控制台

现在有最直观的绘图数据了!下一步就是直接往“画布”上扔就可以了

步骤5:画画

/**
     * 现在有了处理后的数据(pieData)和生成path的arc generator(arc)
     * 可以开始画图了!
     */

     //绑定数据,在g容器中插入g
    const groups = g.selectAll('g').data(pieData)
                    .enter()
                    .append('g');
    //画path
    groups.append('path')
          .attr('d', arc)//将pieData[i]传予arc
          .style('fill', d=>color(d.data.name));

    //画text
    groups.append('text')
          .text(d=>d.data.name)
          .attr('transform', d=>`translate(${arc.centroid(d)})`) //计算path的中心位置
          .attr('dy', '.35em')
          .style('text-anchor', 'middle')
          .style('font-size', '20px');

最后完成

结语

此demo只是最为简单的一个例子,但让人对布局(layout)有了大致的了解。
致于d3的绘图步骤,我在十二月咖啡馆的图的基础上再次总结了一番:

更复杂的图表肯定会有更多的处理,但大体思路如此
以上内容如有不正确之处,还请大佬指教

参考资料

Visualization on the Web Tutorials——Advanced D3: Layouts
十二月咖啡馆——布局
GitHub——D3 Layouts
d3.pie()
d3.arc()