d3.js + React + TS: 数据可视化 1~6

数据可视化-d3.js

1. 环境配置

1.1 配置React + TS

这里使用脚手架配置:

npx create-react-app react-typescript-demo --typescript 

2. 使用D3查询SVG

2.1 d3.select(xxx)

d3.select('#rect1'),查询ID为'rect1'的元素,#表示后面的字
符串是一个ID。

d3.select(xxx)也可用于查询类别,如d3.select(“.class1“),但只会返回找到的第一个元素。

2.2 d3.selectAll(xxx)

d3.selectAll('.class1'),查询所有class是'class1'的元素。
d3.selectAll('rect'),查询所有标签是'rect'的元素(rect为SVG中的矩形标签)。

2.3 基于层级的查询

  • d3.select('#magingroup rect')
  • d3.selectAll('.tick text')
  • d3.selectAll("#secondgroup rect")

如: ’#secondgroup rect‘

  • 首先会找到id为secondgroup的标签。
  • 进一步找到secondgroup的子标签中是rect的。
  • 仍然是对rect做查询,只是结果通过父标签做了筛选!

这种形式的查询,经常会在配置坐标轴的代码中使用,请至少熟悉其形式。

3. 使用D3设置SVG中的属性

3.1 常见属性

  • id,class(特殊属性,可以使用.attr设置)
  • x,y,cx,cy(元的坐标)
  • fill,stroke
  • height,width,r(圆的半径)
  • transform -> translate,rotate,scale

3.2 element.attr(xxx)

  • 设置元素的属性:element.attr(’attr_name‘,’attr_value‘)

    • react1.attr('y', '100');
    • d3.select('#rect1').attr('y', '100');
  • 获取元素的属性:element.attr(’attr_name‘);

  • 注意:数值类型的数据仍在HTML中仍有字符串存储

    • 要使用+(strValue)及时转换,如 let value = +(’233.666‘)
    • 活用模板字符串,如
      • let width = 666;
      • attr(’transform‘,’translate(0, $(width + 100))‘)
      • 模板字符串使用’xxx‘ 表示(本质上还是一个字符串)
      • ${xxx}可以在字符串中嵌入程序表达式

3.3 设置图元属性

  • selection.attr('attrbuteName', 'value')

    • 支持直接通过值来设置属性
    • 支持通过函数来设置属性
  • selection.attr('attrbuteName', (d, i) = > {xxx})

    • d为绑定给图元的数据(即将到来)
    • i为图元的索引,是一个证书,如d3.selectAll('rect')中第几个矩形
    • 函数也可以仅使用d => {xxx},但此时函数体无法使用索引
    • 即使不使用的绑定的数据(如没有绑定数据),如需使用索引,仍需要完整的写出(d, i) => {xxx}

4.1 属性继承

  • DOM

    • 父节点的属性会影响子节点
    • 子节点的属性会相对于父节点
  • 活用节点可以省掉很多冗余代码!

    • d3.select(’#maingroup‘)
    • .attr(’transform‘,’translate(200, 100)‘)

4. 使用D3添加&删除SVG元素

4.1 element.append()

  • element.append()

    • const myRect = svg.append('rect');
    • const myRect = d3.select(’#mainsvg‘).append(’rect‘)
    • const myRect = d3.select(’#mainsvg‘).append(’rect‘).attr(’x‘:’100‘)
  • 链式添加

    • const myReact = d3.select('#mainsvg').append('g').attr('id', 'maingroup')
    • .append('rect').attr('fill', 'yellow')
      链式调用:习惯这种编程习惯有助于使用D3和浏览D3的代码
  • element.remove()

    • 请小心使用,会移除整个标签
  • 在debug的过程中可以考虑使用’opacity‘属性hack出移除的效果。

    • element.attr('opacity', '0')

5. 比例尺

  • 比例尺用于把实际的数据空间映射到屏幕的空间。
  • 比例尺非常重要,会经常同时传给坐标轴与数据!

5.1 Scale-Linear

const xScale = d3.scaleLinear().domain([min_d, max_d]).range([min, max]);

const xScale = d3.scaleLinear().domain([0, d3.max(data, daturm => datum.value)]).range([0, innerWidth]);

d3.max(数局,回调:如果提取数据的值)
d3.max: 求出数据某一属性的最大值,比如年龄的最大值

5.2 Scale-Band

const yScale = d3.scaleBand().domain(list).range([min, max]).padding(p);

const yScale = d3.scaleBand().domain(data.map(datum => datum.name)).range([0, innerHeight]).paading(0.1)

5.3 Scale是函数

  • 通过d3.scaleLinear或d3.scaleBand得到的返回值本质上是函数。

    • 给出数据的值(domain)
    • 返回映射后的值(range)
    • .domain(xxx)和.range(xxx)可以理解为配置这个函数(功能)的过程。
  • 比例尺的定义仍使用链式调用

const xScale = d3.scaleLinear().domain([0, d3.max(data, datum=>datum.value)]).range([0, innerWidth]);
const mapped = xScale(100);

6. 坐标轴

6.1 引入坐标轴

一个坐标轴为一个group(),通常我们需要两个坐标轴
  • 坐标轴中包含:
    • 一个用于横跨坐标轴的覆盖范围
    • 若干个刻度
      • 每个刻度也是一个group
    • 每个刻度下属还会包含一个和一个
      • 用于展示坐标轴的轴线,如左到右或上到下
      • 用于展示坐标轴的刻度值,如实数、性名、日期
    • (可选)一个标签用于描述坐标轴
定义坐标轴(获得结果是函数)
  • const yAxis = d3.axisLeft(yScale);
  • const xAxis = d3.axisBottom(xScale);
  • axisLeft:左侧坐标轴
  • axisBottom:底侧坐标轴
实际配置坐标轴
  • const yAxisGroup = g.append('g').call(yAxis);
  • const xAxisGroup = g.append('g').call(xAxis);

实际配置后会发现中添加了与坐标轴相关的元素。
任何坐标轴在初始化之后会默认放置在坐标原点,需要进一步的平移。

关于selection.call(xxx)

函数的输入为另一个函数。
另一个函数以selection的图元作为输入。
另一个函数中会根据函数体的内容修改selection对应的图元。
定义一个空白的,D3会帮助我们定义好另一个函数,我们通过.call(xxx)让得以在另一个函数中修改。

6. 绘制BarChart

6.1 定义Margin

  • SVG对于D3.js是一个’画布‘。

  • SVG范围外的任何内容属于画布之外,浏览器将不予显示。

  • 定义Margin

    • const margin = {top: 60, right: 30, bottom: 60, left: 200}
  • 计算实际操作的inner 长/宽

    • const innerWidth = width - margin.left - margin.right;
    • const innerHeight = height - margin.top - margin.bottom;
  • 在SVG下额外定义一个组作为新的根节点

    • const g = svg.append('g').attr('id', 'maingroup').attr('transform', 'translate(${margin.left}, ${margin.top})');

d3绘制的时候会贴近坐标轴绘制

原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13757583.html