上一節(jié)中式塌,我們對(duì)數(shù)據(jù)可視化進(jìn)行了一些基本的介紹博敬,包括其選擇器選擇,數(shù)據(jù)綁定方式以及屬性的設(shè)置峰尝,和圖表數(shù)據(jù)的更新等一些操作偏窝,今天,我們來(lái)學(xué)習(xí)制作一些柱狀圖武学,并對(duì)其中用到的一些api 進(jìn)行講解祭往。
svg矩形位置設(shè)定
x: 矩形左上角x軸坐標(biāo)
y: 矩形右上角y軸坐標(biāo)
width: 矩形的寬度
height: 矩形的高度
rx: 對(duì)于圓角矩形,指橢圓在x軸方向的半徑
ry: 對(duì)于圓角矩形火窒,指橢圓在y軸方向的半徑
例如:
<svg width="100mm" height="100mm"> <rect x="20" y="20" width="50" height="50" style="stroke: #f36; fill: rgba(123,123,23,.5);"/> </svg>
坐標(biāo)系統(tǒng)
比例尺
- 線性比例尺
一個(gè)最簡(jiǎn)單的線性關(guān)系: y= 2x +1
在d3 的v4版本中链沼,運(yùn)行可得下列結(jié)果:
let yScale = d3.scaleLinear()
.domain([0, 500])
.range([0, 100]);
console.log( yScale(50) ) //10
console.log( yScale(250) ) // 50
console.log( yScale(450) ) //90
- 序數(shù)比例尺
定量比例尺的定義域和值域都是連續(xù)的,在實(shí)際的使用中沛鸵,很多時(shí)候定義域和值域都是是非連續(xù)的括勺,這時(shí)候我們就要用到序數(shù)比例尺了缆八。
let xScale = d3.scaleBand()
.domain(["a", "b", "c", "d", "e"])
.rangeRound([0, 100])
console.log(xScale("a")) //0
console.log(xScale("d")) //60
console.log(xScale("e")) //80
好了,學(xué)習(xí)上面兩個(gè)知識(shí)點(diǎn)之后疾捍,我們開(kāi)始我們的柱狀圖繪制奈辰!
準(zhǔn)備的數(shù)據(jù)
const data =[
{x:"上海", y:100},
{x:"北京", y:200},
{x:"天津", y:280},
{x:"西安", y:100},
{x:"武漢", y:240},
{x:"長(zhǎng)沙", y:210},
{x:"深圳", y:100},
{x:"鄭州", y:220},
{x:"駐馬店", y:410},
{x:"信陽(yáng)", y:100},
{x:"漯河", y:220},
{x:"商丘", y:210},
{x:"南陽(yáng)", y:100},
{x:"紐約", y:220},
{x:"南昌", y:210}
]
樣式
svg {
box-sizing: content-box
}
界面初始化
在進(jìn)行渲染之前,我們會(huì)先在svg 各側(cè)預(yù)留padding乱豆,這里做的主要目的是為了坐標(biāo)軸數(shù)值部分超出的可以正常顯示奖恰。
var initWidth = 340
var initHeight = 500
var padding = { left:40, top:20, right:10, bottom: 20}
var height = initWidth - padding.top - padding.bottom
var width = initHeight - padding.left - padding.right
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("padding-left", padding.left)
.style("padding-right", padding.right)
.style("padding-top", padding.top)
.style("padding-bottom", padding.bottom)
此時(shí)效果如下:
初始效果
定義坐標(biāo)軸
// y比例尺
let ydata = data.map(function(e, i){ return e.y}) //拿到y(tǒng)軸所有數(shù)據(jù)
let yScale = d3.scaleLinear() //定義線性比例尺(數(shù)值型,等比縮放)
.domain([0, d3.max(ydata)]) // 定義域
.range([height , 0]); //值域
let _yScale = d3.scaleLinear()
.domain([0, d3.max(ydata)])
.range([0, height]);
***上述yScale與 _yScale的差別就在于range恰恰相反宛裕,
因此同樣的數(shù)值在運(yùn)算時(shí)拿到的正好是相反的數(shù)據(jù)瑟啃,
而這在待會(huì)的坐標(biāo)軸數(shù)值計(jì)算和直方位置的計(jì)算中我們會(huì)用到***
//定義y軸
let yAxis = d3.axisLeft(yScale); //這句話的意思是添加左側(cè)坐標(biāo)軸,比例尺使用yScale
//添加y軸
svg.append("g")
.attr("class","axis")
.attr("transform","translate(" + 0 + "," + 0 + ")")
.call(yAxis);
//添加x軸坐標(biāo)軸
//x軸比例尺
let xData = data.map(function(e, i){ return e.x})
let xScale = d3.scaleBand() //定義序數(shù)比例尺
.domain(xData)
.rangeRound([0, width])
.padding(0.1)
//定義x軸
let xAxis = d3.axisBottom(xScale)
//添加x軸
svg.append("g")
.attr("class","axis--x")
.attr("transform","translate(" + "0 ," + height + ")")
.call(xAxis);
此時(shí)效果如下
預(yù)覽
繪制直方
var rect = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", function(d, i){
return xScale(d.x)
})
.attr("y", function(d){
return height - _yScale(d.y)
})
.attr("width", xScale.bandwidth())
.attr("height", function(d){
return _yScale(d.y)
})
.attr("fill", "steelBlue")
效果
預(yù)覽
接下來(lái)揩尸,我們可以在柱上添加文字
var text = svg.append("g")
.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("x", function(d, i){
return xScale(d.x)
})
.attr("y", function(d){
return height - _yScale(d.y)
})
.attr("dy", "1em")
.attr("dx", xScale.bandwidth() / 2)
.attr("text-anchor", "middle")
.attr("font-size", '14px')
.attr("fill", "#fff")
.text(function(d){
return d.y
})
效果如下
預(yù)覽
我們可以給坐標(biāo)軸添加一些樣式讓他看起來(lái)活潑一些
.axis--x path {
display: none;
}
鼠標(biāo)在上面移動(dòng)時(shí)我們可以給他添加一些樣式
var rect = svg.selectAll("rect")
.........
.attr("fill", "steelBlue")
.on("mouseover",function(){
d3.select(this).attr("fill", "yellow")
})
.on("mouseout", function(){
d3.select(this).attr("fill","steelBlue")
})
預(yù)覽
預(yù)覽
接下來(lái)我們給它添加一些交互效果
點(diǎn)擊事件
這個(gè)很簡(jiǎn)單只需這樣一句
var rect = svg.selectAll("rect")
.........
.on("click",function(d){
console.log(d.x+":"+d.y)
})
(框選和點(diǎn)擊不能同時(shí)存在)
框選
var brush = svg.append("g")
.attr("class", "brush")
.call(d3.brushX()
.on("start", function(){ })
.on("brush", function(){ } )
.on("end", function(e) {
var selection = d3.event.selection;
console.log(selection) //可以拿到框選的x軸坐標(biāo)范圍蛹屿,我們通過(guò)這個(gè)數(shù)值拿到框選到的目標(biāo)就很簡(jiǎn)單啦
})
)
最終效果
預(yù)覽
一個(gè)小案例: 使用柱狀圖動(dòng)態(tài)展示冒泡排序
冒泡排序可視化動(dòng)態(tài)展現(xiàn)
本文所有圖表源碼
好了,今天我們先學(xué)到這里岩榆,明天更新餅圖制作 错负!