同樣的線性比例尺,映射的時候,故意給四周留白,就能解決上一章的問題。下面的代碼中,我們定義了 `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()`后,則比例尺輸出的所有值都會舍入到最接近的整數值。對輸出值取整有利于圖形的像素值更精確,避免邊緣出現模糊不清的鋸齒。