携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 27 天,点击查看活动详情
前因
在上一节中,我们讲解了关于 SVG
相关的基本操作,并且在最后留了一个示例,通过 D3
实现了 柱状图
,这一节我们就继续来学习关于 SVG
相关的操作。
柱状图
首先我们还是接着上一节结尾的 柱状图
来继续学习,我们要生成一个 柱状图
,就需要先准备相关的数据,类似下面这样:
interface BarChartType {
name: string;
value: number;
}
const data: BarChartType[] = [
{name: 'ShaoKei1', value: 6},
{name: 'ShaoKei2', value: 6},
{name: 'ShaoKei3', value: 13},
{name: 'ShaoKei4', value: 8},
{name: 'ShaoKei5', value: 20},
...
];
有了数据后,我们需要选择将要操作的元素,就需要使用 select
来获取元素的索引,如下:
const svg = d3.select('#svg');
我们要创建一个 柱状图
,就需要定义 柱状图
中的横坐标比例尺
和纵坐标比例尺
,关于比例尺
在上一节做了简单的介绍,这里只要知道我们是要获取横坐标和纵坐标的数据即可,代码如下:
// 需要获取到画布的宽高
const width = +svg.attr('width');
const height = +svg.attr('height');
const xScale = d3.scaleLinear()
.domain()
.range();
const yScale = d3.scaleBand()
.domain()
.range();
我们在前面已经了解过,如果要给一个元素设置属性,就需要用到attr
,当然attr
这个API
不仅可以用于设置值,也可以用于获取值,只需要在最前面添加+
号,并且attr
的参数只设置第一个,就可以获取到对应的值,如上所示。
当然,我们虽然获取到了画布的宽高,但是为了防止将坐标轴画到画布的外面,我们就需要设置相关的起点,如下:
const margin = { top: 60, right: 40, bottom: 60, left: 40 };
因为我们设置了相关的起点,所以我们真正能够画图的区域就缩小了,如下所示:
const iWidth = width - margin.left - margin.right;
const iHeight = height - margin.top - margin.bottom;
当我们设置好相关的位置后,我们就可以设置比例尺中的相关数据了,如下:
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, (item: BarChartType) => item.value)])
.range([0, innerWidth]);
const yScale = d3.scaleBand()
.domain(data.map((item: BarChartType) => item.name))
.range([0, innerHeight])
.padding(0.1);
在上述的代码中,我们通过range
设置坐标轴的起点和终点,起点是0,终点就是我们前面计算的可以实际操作的画布的大小。然后在domain
中是我们需要设置的数据,也就是这个 柱状图
实际的值展示出来后的样子,在 D3
中有一些数组的静态方法,d3.max
就是用于获取数组中最大的值,通过这个 API
,我们就能拿到数组用最大的值。
我们需要将坐标画在画布上,就需要先创建相关的标签,然后进行统一的设置,代码如下:
const g = svg.append('g')
.attr('id', 'svg')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
当我们已经将 柱状图
中的横纵坐标的数据都准备后,我们就可以在画布中根据前面的 data
数据来画图了,这时候就需要先计算出相关的坐标位置,代码如下:
const yAxis = d3.axisLeft(yScale);
g.append('g').call(yAxis);
上述的代码中,通过 d3.axisLeft
设置左侧纵坐标的位置,最终的效果如下图所示:
有了纵坐标,那么我们还需要将横坐标也展示出来,代码如下:
const xAxis = d3.axisBottom(xScale);
g.append('g').call(xAxis).attr('transform', `translate(0, ${iHeight})`);
设置完横纵坐标后,最终的效果如下图所示:
我们在上面已经完成了坐标轴的渲染,接下来我们就需要将 data
中的数据通过循环画到画布上,具体代码如下:
data.forEach((item: BarChartType) => {
g.append('rect')
.attr('width', xScale(item.value))
.attr('height', yScale.bandwidth())
.attr('fill', 'pink')
.attr('y', yScale(item.name));
});
通过 append
创建一个 rect
元素,然后给它设置相关的属性,最终展示如下图所示:
当然,左侧的纵坐标的文字太小了,我们需要修改一下,但 D3
是不支持直接修改文字大小的,我们可以通过选取到这些文字所在的标签进行修改,如下所示:
d3.selectAll('.tick text').attr('font-size', '2em');
我们还添加一个 柱状图
的标题,这个示例就完成了,代码如下:
g.append('text').text('Bar Chart')
.attr('font-size', '3em')
.attr('transform', `translate(${iWidth / 2}, 0)`)
.attr('text-anchor', 'middle');
完成后的最终样式如下图所示:
你可以狠戳这里进行代码的查看。
最后
我们在这一节继续加深了对 SVG
操作的学习,并且将上一节中最后留的案例进行了拆分讲解,相信通过这两节基本操作的学习,我们已经学会了使用 D3 对 SVG 进行操作,并完成相关的案例,我们一起加油吧!
未完待续...
最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家