同样的线性比例尺,映射的时候,故意给四周留白,就能解决上一章的问题。下面的代码中,我们定义了 `space = 20`,让`svg`的四周都留下20个单位不使用。
```
var dataset = [[1, 1], [2, 3], [5, 8], [13, 21], [34, 55]];
var w = 500;
var h = 200;
var padding = 3; //两个柱形之间的缝隙
var space = 20; //svg四周留白
var x_width = (w - padding * dataset.length) / dataset.length; // 横坐标的宽度
var yScale = d3.scaleLinear() //线性比例尺
.domain([0, d3.max(dataset, d=>d[1])]) //值域的范围
.range([space, h-space]); //映射到可视的区域,修改可视区域
var rScale = d3.scaleSqrt() //平方根比例尺
.domain([0, d3.max(dataset, d=>d[1])])
.range([padding, 20-padding]); //修改可视区域
d3.select('body').append('svg')
.attr('width', w).attr('height', h)
.selectAll('circle').data(dataset).enter().append('circle')
.attr('cx', (d, i) => space+i * (x_width + padding)) //圆心的x
.attr('cy', d => h - yScale(d[1])) //圆心的y,注意坐标0点在左上角
.attr('r', d => rScale(d[1])) //取y的平方根作为半径
.attr('fill', 'teal')
```
计算机不能处理0.5个像素,所以比例尺的输出如果是小数的话,可能会出现锯齿问题,你可以采用下面的几个方法消除。
## nice 方法
输出优化操作。比如,值域\[0.2015435434, 0.95432543\]可能被优化为\[0.2, 1.0\]。只要在定义比例尺的后面,继续调用`nice()`方法即可。
```
var yScale = d3.scaleLinear() //线性比例尺
.domain([0, d3.max(dataset, d=>d[1])]) //值域的范围
.range([space, h-space]) //映射到可视的区域,修改可视区域
.nice(); //优化小数
```
## clamp 方法
如果输入超出了`domain`的值域,默认的比例尺方法的返回值也会超出`range`的范围的。如果调用调用`clamp()`就能保证输出不超过指定的范围了。
```
var scale = d3.scaleLinear() //线性比例尺
.domain([0, 100]) //值域的范围
.range([10, 20]) //映射到可视的区域,修改可视区域
.clamp(true); //固定输出范围
//scale(1000) //20
```
## rangeRound 方法
用`rangeRound()`代替`range()`后,则比例尺输出的所有值都会舍入到最接近的整数值。对输出值取整有利于图形的像素值更精确,避免边缘出现模糊不清的锯齿。