zzxworld

使用 D3.js(v7) 绘制折线图

这几天一直在学习 D3.js 的使用,并连续总结了两篇相关的入门级文章。今天继续趁热打铁,了解一下折线图的绘制方法。

D3.js 作为一个数据图形化工具,对绘图过程中需要用到的一些功能都提供了相应的方法,而且流程上大同小异。所以从本篇开始,不会再以「由浅入深」的方式来讲解具体绘制过程。需要了解基础使用方法和流程请参考之前的两篇入门级文章:

通过以上两篇文章了解了 D3 的「绘图套路」后,接下来就是举一反三,多看多练习的实践,掌握 D3 不是难事。

先来看看本文实践的最终效果:

D3 折线图

图表代码如下:

// 定义数据集
var dataset = [2, 10, 35, 60, 70, 100, 90]

// 定义图表画布参数
var width = 800
var height = 400
var padding = 30
var svg = d3.select('svg')
    .attr('width', width)
    .attr('height', height)

// 定义坐标轴
var xScale = d3.scaleLinear()
    .domain([0, dataset.length-1])
    .range([0, width-padding*2])
var xAxis = d3.axisBottom(xScale).ticks(dataset.length)

var yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset)])
    .range([height-padding*2, 0])
var yAxis = d3.axisLeft(yScale)

// 绘制坐标轴
svg.append('g').call(xAxis)
    .attr('transform', 'translate(40, '+(height-padding)+')')
svg.append('g').call(yAxis)
    .attr('transform', 'translate(40, '+padding+')')

// 绘制折线
var line = svg.append('g')
    .attr('transform', 'translate(40, '+padding+')')

line.append('path')
    .datum(dataset)
    .attr('fill', 'none')
    .attr('stroke', 'blue')
    .attr('stroke-width', 1)
    .attr('d', d3.line().x((v, i) => {
        return xScale(i)
    }).y((v, i) => {
        return yScale(v)
    }))

// 绘制数据坐标圆点
line.selectAll('circle').data(dataset).enter()
    .append('circle')
    .attr('cx', (v, i) => { return xScale(i)})
    .attr('cy', (v, i) => { return yScale(v)})
    .attr('r', 5)
    .attr('fill', 'gold')
    .attr('stroke', 'blue')

    // 定义鼠标移入事件
    .on('mouseover', function (e, v) {
        // 放大坐标圆点
        d3.select(this).attr('r', 7)

        // 在光标上方显示坐标值
        var pos = d3.pointer(e)
        svg.append('text')
            .text(v)
            .attr('class', 'tooltip')
            .attr('x', pos[0]+50)
            .attr('y', pos[1]+20)
            .attr('text-anchor', 'end')
    })

    // 定义鼠标移出事件
    .on('mouseout', function () {
        // 还原坐标圆点
        d3.select(this).attr('r', 5)
        // 移除坐标值提示标签
        d3.select('.tooltip').remove()
    })

代码中的关键位置都有注释,这里就不重复说明了。代码行数看起来虽多,但就像上面说的,如果熟悉了 D3 的用法就会发现,大部分都是一些设置位置和大小的属性操作,没有什么技术难点。