D3.js - 图表绘製

上一篇介绍了 D3.js 的基础,这篇会边绘製图表边介绍绘製的方法,我们会使用到 SVG,还不熟悉 SVG 也可以参考下面的文章哦
SVG - 基础图形与样式
SVG - 进阶功能介绍

方法

因为 D3 实在有太多方法了,这边我们只介绍比例尺与座标轴的绘製,如果想了解所有方法可以参考这里

比例尺

绘製图表时,资料常常有大有小,而比例尺就是将资料等比例转换到某个幅度内

d3.min():取阵列最小值d3.max():取阵列最大值d3.scaleLinear():建立一个比例尺domain():定义资料範围range():定义图表资料範围rangeRound():同 range,但会将结果四捨五入clamp(true):将超过範围的值设为最大值 or 最小值,预设为 falseunknown:将 undefinedNaN 转为指定数值ticks:将图表资料分为数个区间
const dataset = [0, 33, 65, 199.9, 454, 887.5, 1000]const min = d3.min(dataset) // 0const max = d3.max(dataset) // 1000const scale = d3  .scaleLinear()  .domain([min, max])  .range([0, 100])console.log(scale(99))   // 9.9,若使用 rangeRound 则为 10console.log(scale(500))  // 50console.log(scale(1001)) // 0console.log(scale(-1))   // 0console.log(scale(NaN))  // 母汤乱输入

座标轴

座标轴可以让资料与图表更容易检视,另外也需要用到上面说到的比例尺~

d3.axisTop:建立上方座标轴d3.axisRight:建立右方座标轴d3.axisBottom:建立下方座标轴d3.axisLeft:建立左方座标轴ticks:指定资料的区间数量,预设为 10tickValues:显示特定座标值,需传入阵列tickSize:调整刻线长度tickPadding:调整刻线与数值的距离tickFormat:可传入函式自订数值格式
const dataset = [0, 33, 69, 59, 100]const chart = d3  .select('.chart')  .attr('width', 400)  .attr('height', 400);        const scale = d3  .scaleLinear()  .domain([0, d3.max(dataset)])  .range([0, 100])const axis = d3  .axisBottom(scale)  .ticks(5)  .tickSize(20)  .tickPadding(20)  .tickFormat(item => item + '分');chart.append('g').call(axis)// axis(chart.append('g'))// 上面的方法与 call 效果相同,皆是将坐标轴绘製出来

坐标轴範例

图表种类与绘製

上面介绍了许多基本技巧,接下来就要使用上面学到的来画各式各样的图啰,html 如下

<body>  <svg class="chart"></svg></body>

长条图

// 以下七胖团员的朋友人数,当然是我掰的XD const sevenFat = [  { name: 'HowHow', friend: 3 },  { name: '蔡 Brother', friend: 13 },  { name: '阿嘎', friend: 25 },  { name: '马叔叔', friend: 8 },  { name: 'RJ', friend: 10 }]// 设定 svg 的宽高const chart = d3  .select('.chart')  .attr('width', 500)  .attr('height', 500);// 选取所有的 g 群组const group = chart  .selectAll('g')  .data(sevenFat)  .enter()  .append('g');// 取比例尺const scale = d3  .scaleLinear()  .domain([0, d3.max(sevenFat.map(item => item.friend))])  .range([0, 300]);// 绘製长条图group  .append('rect')  .attr('x', 100)  .attr('y', (item, i) => i * 25)  .attr('width', item => scale(item.friend))  .attr('height', 25 - 2)  .attr('fill', 'steelblue');// 显示名字group  .append('text')  .attr('x', 0)  .attr('y', (item, i) => i * 25 + 18)  .style('fill', 'black')  .style('font-size', '18px')  .style('font-weight', 'bold')  .text(item => item.name);// 显示朋友数量group  .append('text')  .attr('x', (item, i) => 95 + scale(item.friend))  .attr('y', (item, i) => i * 25 + 18)  .attr('text-anchor', 'end')  .style('fill', 'black')  .style('font-size', '18px')  .style('font-weight', 'bold')  .text(item => item.friend);  // 显示坐标轴const axis = d3  .axisBottom(scale)  .ticks(5)  .tickFormat(item => item + '人');  chart  .append('g')  .call(axis)  .attr('transform', 'translate(100,125)');

长条图範例

散布图

// 以下小弟打靶成绩,中心点为 (50, 50) const shot = [  { x: 10, y: 96 },  { x: 90, y: 13 },  { x: 77, y: 89 },  { x: 25, y: 35 },  { x: 13, y: 6 }];// 设定 svg 的宽高const chart = d3  .select('.chart')  .attr('width', 500)  .attr('height', 500);// 选取所有的 g 群组const group = chart  .selectAll('g')  .data(shot)  .enter()  .append('g');// 取 X 轴比例尺const scaleX = d3  .scaleLinear()  .domain([0, 100])  .range([0, 300]);// 显示 X 坐标轴const axisX = d3.axisBottom(scaleX);chart  .append('g')  .call(axisX)  .attr('transform', 'translate(30,330)');// 取 Y 轴比例尺const scaleY = d3  .scaleLinear()  .domain([100, 0])  .range([0, 300]);// 显示 Y 坐标轴const axisY = d3.axisLeft(scaleY);chart  .append('g')  .call(axisY)  .attr('transform', 'translate(30,30)');// 绘製座标点group  .append('circle')  .attr('cx', item => scaleX(item.x))  .attr('cy', item => scaleY(item.y))  .attr('r', '2px')  .attr('height', 25 - 2)  .attr('fill', 'red')  .attr('transform', 'translate(30,30)');// 显示座标group  .append('text')  .attr('x', item => scaleX(item.x))  .attr('y', item => scaleY(item.y))  .style('fill', 'black')  .style('font-size', '10px')  .style('font-weight', 'bold')  .text(item => `(${item.x},${item.y})`)  .attr('transform', 'translate(35,25)');

散布图範例

折线图

折线图就要多介绍到一些绘製 path 的方法啦~

d3.line:定义一个线段x:传入一个涵式,定义 x 座标y:传入一个涵式,定义 y 座标curve:将路径更改为曲线,详细可参考这里
// 前公司每个月产品的产量const report = [  { month: 1, quantity: 8561 },  { month: 2, quantity: 9347 },  { month: 3, quantity: 10335 },  { month: 4, quantity: 9900 },  { month: 5, quantity: 12012 },  { month: 6, quantity: 10300 },  { month: 7, quantity: 13020 },  { month: 8, quantity: 15300 },  { month: 9, quantity: 17210 },  { month: 10, quantity: 13400 },  { month: 11, quantity: 11059 },  { month: 12, quantity: 9900 }];// 设定 svg 的宽高const chart = d3  .select('.chart')  .attr('width', 500)  .attr('height', 500);// 选取所有的 g 群组const group = chart  .selectAll('g')  .data(report)  .enter()  .append('g');// 取 X 轴比例尺const scaleX = d3  .scaleLinear()  .domain([0, d3.max(report.map(item => item.month))])  .range([0, 300]);// 显示 X 坐标轴const axisX = d3.axisBottom(scaleX);chart  .append('g')  .call(axisX)  .attr('transform', 'translate(50,330)');// 取 Y 轴比例尺const scaleY = d3  .scaleLinear()  .domain([d3.max(report.map(item => item.quantity)), 0])  .range([0, 300]);// 显示 Y 坐标轴const axisY = d3.axisLeft(scaleY);chart  .append('g')  .call(axisY)  .attr('transform', 'translate(50,30)');// 定义线段const line = d3  .line()  .x(item => scaleX(item.month))  .y(item => scaleY(item.quantity))  .curve(d3.curveBasis);// 将线段绘製出来group  .append('path')  .attr('d', line(report))  .attr('transform', 'translate(50,30)')  .attr('stroke', 'black')  .attr('stroke-width', 1)  .attr('fill', 'none');

折线图範例

结语

这篇画了三种基本的图表,分别为长条图、散布图与折线图,简单的使用了 D3 提供的方法来绘製,其实画起来并不难,D3 帮我们处理掉许多底层的部分,接下来只要够了解 SVG 就能够轻易的画出漂亮的图了,那就祝大家画图表愉快拉~


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章