D3篇之绘制基本图形

数据准备:<div ref="dataRef" :class="$style.dataRef"></div>

 const fData = [
        {
          name: '香蕉',
          value: 20
        },
        {
          name: '苹果',
          value: 30
        },
        {
          name: '李子',
          value: 90
        },
        {
          name: '猕猴桃',
          value: 10
        },
        {
          name: '橙子',
          value: 60
        }
      ];
      const margin = { left: 30, top: 30, bottom: 30, right: 30 };
      const width = 300;
      const height = 300;
      const svg = d3.create('svg').attr('viewBox', [30, 30, width, height]);
      //...要进行的操作
      this.$refs.dataRef.appendChild(svg.node());

1.柱状图 

scaleBand

  • 适用于离散型数据或分类数据,比如类别、名称等,而不是连续的数值。
  • 常用于创建序数型比例尺(Ordinal Scale),它将离散的输入域映射到有限的输出范围内。
  • domain 包含离散的、有限的值,通常是类别的名称或者离散的标识。
  • 通常用于创建柱状图、分组条形图等,以及将分类数据映射到屏幕上的位置。

const x = d3
  .scaleBand()
  .domain(['A', 'B', 'C', 'D']) // 例如,类别或离散标识
  .range([0, width])
  .padding(0.1); 

 1-1.绘制x轴

const x = d3
        .scaleBand()
        .domain(d3.map(fData, d => d.name))
        .range([margin.left, width - margin.left]);
      const xAxis = d3.axisBottom(x).tickSizeOuter(0);
      svg
        .append('g')
        .attr('transform', `translate(${margin.left},${height - margin.bottom})`)
        .call(xAxis);

1-2.绘制y轴

scaleLinear

  • 适用于连续型数据,比如数值型数据。
  • 创建的是线性比例尺(Linear Scale),将输入域的连续范围映射到输出范围内。
  • domain 包含连续的数值范围,通常是最小值到最大值的数值范围。
  • 通常用于创建折线图、散点图等,以及将数值数据映射到屏幕上的位置。
 const y = d3
        .scaleLinear()
        .domain([min, max])
        .range([margin.bottom, height - margin.bottom]);
      const yAxis = d3.axisLeft(y);
      svg.append('g').attr('transform', `translate(${margin.left},0)`).call(yAxis);

 

是不是很惊奇,为什么压轴是从上往下变大的?

      在可视化中,特别是在屏幕坐标系中,通常情况下,y轴的原点通常位于屏幕的左上角,而不是传统的数学坐标系中的左下角。在屏幕坐标系中,y轴向下增长,这与我们在数学课堂上使用的笛卡尔坐标系中y轴向上增长是不同的。

这种不同是因为计算机图形学的历史和屏幕显示的方式导致的。在大多数图形库中,包括D3.js,在渲染坐标轴时,默认情况下会将y轴从上到下显示,这也是为了与屏幕坐标系的方向保持一致。

虽然y轴的增长方向与我们直觉上的数学坐标系不同,但在实际的可视化中,这种方向是合理的,并且符合我们对屏幕空间的感知。如果你想要y轴向上增长,可以通过反转坐标轴的range来实现

const y = d3.scaleLinear().domain([min, max]).range([height - margin.bottom, margin.bottom]);

1-3.画条形图

在页面中添加rect和text实现条形图

修改之前代码如下:

svg
        .append('g')
        .attr('transform', `translate(0,${height - margin.bottom})`)
        .call(xAxis)
        .call(g => {
          g.selectAll('.tick')
            .append('rect')
            .data(fData)
            .join('rect')
            .attr('width', 30)
            .attr('height', d => height - margin.bottom - y(d.value))
            .attr('fill', 'pink')
            .attr('transform', d => `translate(-15,-${height - margin.bottom - y(d.value)})`);
        })
        .call(g =>
          g
            .selectAll('.tick')
            .append('text')
            .data(fData)
            .join('text')
            .attr('class', 'txt')
            .attr('x', 0)
            .attr('y', d => -(height - margin.bottom - y(d.value)) - 5)
            .attr('text-anchor', 'middle')
            .attr('fill', 'red')
            .text(d => d.value)
        );

 

2.折线图

绘制x轴和y轴原理同上,不同的就吧条形图换成折线图,下面仅是实现折现代码

2-1.绘制折现 

在数据可视化中,曲线(Curves)通常指的是用来平滑连接数据点的线条或路径。在 D3.js 中,有多种类型的曲线插值器可以用来创建平滑的曲线路径,用于连接给定的数据点。

d3.line() 是 D3.js 中的一个函数,用于创建生成器(Generator)。这个生成器可以将输入的数据点数组转换为 SVG <path> 元素所需的路径字符串,以便在 SVG 中绘制线条或曲线。

通常,d3.line() 生成器会配置以下属性:

  • x: 用于确定数据点的 x 坐标的函数或值。
  • y: 用于确定数据点的 y 坐标的函数或值。
  • curve: 确定路径的曲线插值器类型,例如线性、基数样条、单调等。

使用 D3.js 创建的 line 可以将数据点转换为 SVG 中的路径,然后将这个路径添加到 SVG 中以显示图形。要将 line 添加到 SVG 中,你需要将路径数据绑定到一个 SVG 元素上,并将路径信息设置为这个元素的 d 属性。

const line = d3
        .line()
        .x(d => x(d.name))
        .y(d => y(d.value))
        .curve(d3.curveLinear);//d3.curveLinear可根据官网更改
      svg
        .append('path')
        .datum(fData)
        .attr('d', line)
        .attr('fill', 'none')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', 2);

2-2.给折线图添加面积 

 const area = d3
        .area()
        .x(d => x(d.name)) // 定义x坐标
        .y0(height - margin.bottom) // 定义y坐标的底部值,通常是图表底部
        .y1(d => y(d.value)); // 定义y坐标的顶部值,基于数据的值

      svg.append('path').datum(fData).attr('d', area).attr('fill', 'steelblue').attr('opacity', 0.4);

注意:这里x轴要添加.paddingInner(1)设置分组间的内边距

Band scales | D3 by Observable

3.饼图

Arcs | D3 by Observable

Pies | D3 by Observable

3-1.数据转换弧度

 const pie = d3.pie()(fData.map(d => d.value));

arc弧形生成器产生圆形或环状扇形,例如馅饼或甜甜圈图表。弧线以原点为中心;变换来将弧线移动到不同的位置。 

 const pie = d3.pie()(fData.map(d => d.value));
      // 设置每个值的弧度
      const arc = d3
        .arc()
        .innerRadius(0)
        .outerRadius(80)
        .startAngle(d => d.startAngle)
        .endAngle(d => d.endAngle);
      svg
        .selectAll('g')
        .data(pie)
        .join('g')
        .attr('transform', 'translate(100,100)')
        .call(g =>
          g
            .append('path')
            .attr('d', arc)
            .attr('fill', (d, i) => {
              const color = d3.schemeCategory10;
              return color[i];
            })
        )
        .call(g =>
          g
            .append('text')
            .attr('transform', d => `translate(${arc.centroid(d)})`)
            .attr('text-anchor', 'middle')
            .attr('fill', 'white')
            .text(d => d.value)
        );

4.雷达图

areaRadiallineRadial 是 D3.js 中用于创建极坐标图表的两个不同的生成器。它们的区别在于它们的输出和用途。

  1. lineRadial 生成器:

    • 用于创建连接数据点的径向线。
    • 输出是一条连接各个数据点的线段。
    • 可以用于绘制雷达图的边缘轮廓或其他径向线性图表。
    • const line = d3.lineRadial() .angle(d => /* 角度值 */) .radius(d => /* 半径值 */);

  2. areaRadial 生成器:

    • 用于创建填充了数据区域的径向区域图。
    • 输出是一个封闭的区域,通过指定的曲线描绘出数据的形状。
    • 通常用于绘制雷达图的填充区域,显示数据在各个维度上的分布情况。
    • const area = d3.areaRadial() .angle(d => /* 角度值 */) .radius(d => /* 半径值 */);

在上述代码中,angleradius 方法用于指定在极坐标中数据点的角度和半径的映射。这两个生成器都可以与适当的比例尺(如 scaleBandscaleLinearscaleRadial)一起使用,以确保数据正确地映射到图表中。

总体来说,lineRadial 主要用于绘制连接数据点的线,而 areaRadial 用于绘制填

Radial area chart / D3 | Observable 参考官方这个案例更改

4-1.绘制比例尺

const width = 400;

      const height = 400;

      const innerRadius = 0;

      const outerRadius = width / 2;

      const svg = d3.create('svg').attr('viewBox', [-width / 2, -height / 2, width, height]);

      const x = d3

        .scaleBand()

        .domain(d3.map(fData, d => d.name))

        .range([0, 2 * Math.PI]);

      const y = d3.scaleRadial().domain([0, 100]).range([innerRadius, outerRadius]);

  this.$refs.dataRef.appendChild(svg.node());

 

4-2.绘制形状

   const area = d3
        .areaRadial()
        .curve(d3.curveLinearClosed)
        .angle(d => x(d.name))
        .innerRadius(y(min))
        .outerRadius(y(max));
 svg
        .append('path')
        .attr('fill', 'lightsteelblue')
        .attr('fill-opacity', 0.2)
        .attr('d', area(fData))
        .attr('stroke', 'currentColor');
      svg
        .append('g')
        .selectAll('g')
        .data(fData)
        .join('g')
        .call(g =>
          g
            .append('path')
            .attr('stroke', '#000')
            .attr('stroke-opacity', 0.2)
            .attr(
              'd',
              d => `
            M${d3.pointRadial(x(d.name), innerRadius)}
            L${d3.pointRadial(x(d.name), outerRadius)}
          `
            )
        );

 

4-3.根据数据绘制区域

 

   const line = d3
        .lineRadial()
        .curve(d3.curveLinearClosed)
        .angle(d => x(d.name));
      svg
        .append('path')
        .attr('fill', 'pink')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', 1.5)
        .attr('d', line.radius(d => y(d.value))(fData));

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值