学习D3.js(八)散点图多符号

869 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

开始绘制

引入D3模块

  • 这里引入的是整个D3模块。最近D3官网的CDN有点问题,这里就直接全部引入。
<script src="https://d3js.org/d3.v7.min.js"></script>

数据

  • 自定义数据格式。
    var bColor = ['#4385F4', '#34A853', '#FBBC05', '#E94335', '#01ACC2', '#AAACC2']
    var dataArr = [
      [
        {
          x: 70.5,
          y: 0.5,
          shape: 0
        },
        {
          x: 30.5,
          y: 30.5,
          shape: 0
        },
        {
          x: 50.5,
          y: 20.5,
          shape: 0
        },
        {
          x: 60.5,
          y: 10.5,
          shape: 0
        },
        {
          x: 20.5,
          y: 70.5,
          shape: 0
        },
        {
          x: 70.5,
          y: 70.5,
          shape: 0
        },
        {
          x: 60.5,
          y: 90.5,
          shape: 0
        },
        {
          x: 70.5,
          y: 10.5,
          shape: 0
        },
        {
          x: 10.5,
          y: 30.5,
          shape: 0
        },
        {
          x: 30.5,
          y: 20.5,
          shape: 0
        }
      ],
      [
        {
          x: 71.5,
          y: 2.5,
          shape: 1
        },
        {
          x: 30.5,
          y: 60.5,
          shape: 1
        },
        {
          x: 50.5,
          y: 70.5,
          shape: 1
        },
        {
          x: 60.5,
          y: 50.5,
          shape: 1
        },
        {
          x: 10.5,
          y: 70.5,
          shape: 1
        },
        {
          x: 60.5,
          y: 60.5,
          shape: 1
        },
        {
          x: 90.5,
          y: 90.5,
          shape: 1
        },
        {
          x: 70.5,
          y: 10.5,
          shape: 1
        },
        {
          x: 20.5,
          y: 30.5,
          shape: 1
        },
        {
          x: 80.5,
          y: 10.5,
          shape: 1
        }
      ]
    ]

添加画布

  • 初始化画布。
    var svg = d3
      .select('.d3Chart')
      .append('svg')
      .attr('width', width)
      .attr('height', height)
      .style('background-color', '#1a3055')
    // 图
    var chart = svg.append('g').attr('transform', `translate(${margin * 2}, ${margin})`)

创建比例尺

  • 根据需求创建比例迟。
    // 线性比例尺
    var xScale = d3.scaleLinear().range([0, 400]).domain([0, 100])
    // 线性比例尺
    var yScale = d3.scaleLinear().range([400, 0]).domain([0, 100])
    // 序数比例尺 颜色
    let colorScale = d3.scaleOrdinal().domain(d3.range(0, dataArr.length)).range(bColor)

绘制坐标轴

  • 和折线图一样,根据比例尺使用axis模块自动绘制坐标轴。
    // 坐标轴
    const xAxis = d3.axisBottom(xScale).tickSize(-400)
    chart.append('g').attr('transform', `translate(0, ${400})`).call(xAxis)
    // 坐标轴
    const yAxis = d3
      .axisLeft()
      .scale(yScale)
      .tickSize(-400)
      .tickFormat((d) => {
        return d + '%'
      })
    chart.append('g').attr('transform', 'translate(0, 0)').call(yAxis)
    d3.selectAll('.d3Chart text').style('fill', '#fff')
    d3.selectAll('.d3Chart line').style('stroke', '#fff')
    d3.selectAll('.d3Chart path').style('stroke', '#fff')

image.png

  • 和上一节一样使用.tickSize()绘制网格。

绘制散点

const groups = chart.append('g').selectAll().data(dataArr)

const points = groups
  .enter()
  .append('g')
  .attr('fill', (d, i) => bColor[i])
  .selectAll()
  .data((d) => d)
  • 创建绘制组g,绑定数据。
  • 为每一种类型创建新的组g,绑定点数据。
    points
      .enter()
      .append('path')
      .attr('transform', (d) => 'translate(' + xScale(d.x) + ',' + yScale(d.y) + ')')
      .attr('class', 'pathCircle')
      .attr(
        'd',
        d3
          .symbol()
          .type(function (d) {
            return d3.symbols[d.shape]
          })
          .size(1)
      )
      .transition()
      .duration(500)
      .attr(
        'd',
        d3
          .symbol()
          .type(function (d) {
            return d3.symbols[d.shape]
          })
          .size(100)
      )

2.gif

  • 对每个数据绘制形状。
  • 使用d3.symbol()创建初始形状,然后添加动画。由小变大。
  1. d3.symbol() 创建一个新的符号生成器。
  2. d3.symbols 数组。0~6 对应D3中绘制好的形状。
  3. symbol.type() 设置符号的类型。
  4. symbol.size() 设置符号的大小。

交互动画

function arcTweenMouse(type) {
      return function () {
        if (type) {
          d3.select(this)
            .transition()
            .attr(
              'd',
              d3
                .symbol()
                .type(function (d) {
                  return d3.symbols[d.shape]
                })
                .size(300)
            )
        } else {
          d3.select(this)
            .transition()
            .attr(
              'd',
              d3
                .symbol()
                .type(function (d) {
                  return d3.symbols[d.shape]
                })
                .size(100)
            )
        }
      }
    }
    d3.selectAll('.pathCircle').on('mouseover', arcTweenMouse(true)).on('mouseout', arcTweenMouse(false))

3.gif

  • 通过标识符获取符号对象。
  • 监听鼠标事件,放大缩小符号。
  • 代码地址