书接上回,我们上次用d3实现了画出柱形,这次我们实现完整的柱形图。
基础概念
比例尺
比例尺,简而言之,就是将一组数据映射到另一组数据上,用法理解就是,把我们要展示的数据,映射成相应的像素,比如我们的x轴,位置从0到100即输出域,要展示的数据即输入域,最小值是20,最大值是80,那比例尺的作用就是将20按比例转成0,80按比例转成100。
这里主要用到两个函数
- domain 设置输入域的指定数组
- range 设置刻度的输出范围值的指定数组
这一次我们主要用到两种比例尺
scaleBand 序数比例尺
把离散的定义域映射到线性的定义域上,比如把[a,b,c],映射到[0,90]上,那a会被映射在0,b在45,c在90
scaleLinear 线性比例尺
把连续的定义域映射到线性的定义域上
开始制作
- 先定义好我们柱形图的数据,还有svg的宽高,边距
const dataset = [11, 31,14, 49, 24, 17, 88, 18, 65 ];
const w = 500;
const h = 300;
const margin = {
padding: 20,
bottom: 20,
left: 30
}
- 创建一个svg
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
- 建立两个比例尺,因为我要用数据的序号做x轴,所以一个用序数比例尺,一个用线性比例尺
let x = d3.scaleBand()
.domain(dataset.map((item,index) => index))
.range([margin.left,w - margin.left])
.padding(0.1)
let y = d3.scaleLinear()
.domain([0, d3.max(dataset)]).nice()
.range([h-margin.bottom, margin.bottom])
- 创建x轴和y轴
xAxis = g => g.attr("transform", `translate(0,${h - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
yAxis = g => g.attr("transform", `translate(${margin.left},0)`).call(d3.axisLeft(y))
svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
-
axisBottom 构建一个刻度在下的坐标轴生成器,方向水平
-
axisLeft 构建一个刻度在左的坐标轴生成器,方向垂直
-
同时用transform移动他们到合适的位置
现在可以看到效果
- 接下来就是画上矩形
svg.append('g')
.selectAll('rect')
.data(dataset)
.join('rect')
.attr('height', d => y(0) - y(d))
.attr('width', d => x.bandwidth())
.attr('x', (d,index) => x(index))
.attr('y', d => y(d))
.attr("fill", "pink");
- 效果完成