從本篇博客開始,我將使用D3來完成一些基礎的demo,關於數據可視化方面的介紹我就不多說了,關於d3的簡單介紹:
D3 的全稱是(Data-Driven Documents),一個被數據驅動的文檔。聽名字有點抽象,說簡單一點,其實就是一個 JavaScript 的函數庫,主要是用來做數據可視化,將強大的可視化組件應用於需求中。
查看這個系列的代碼前,請先熟悉一些d3基礎知識,關於基礎可移步至官網:
首先我們先來看看,要實現的柱狀圖的效果:
簡單分析一下:
1.首先我們需要一張畫布。
2.柱體由長方形構成,並且高度由數據驅動顯示。
3.由於柱體的寬度和高度剛好近似鋪滿整個畫布,所以需要用到比例尺
4.柱體上有對應數據顯示,大於30的文字被標紅。
下面來看一些重要的代碼塊:
//線性比例尺
const linear = d3.scaleLinear()
.domain([0, d3.max(datalist)])
.range([2, 398])
//序數比例尺
const scaleBand = d3.scaleBand().domain(d3.range(0,datalist.length))
.range([10, 490])
.paddingInner(0.08)
;
上面是兩個比例尺,線性比例尺被用於柱體的高度相關,而序數比例尺被用於柱體的寬度相關。
(畫布的寬度是500,高度是400)
container.selectAll('rect')
.data(datalist)
.enter()
.append('rect')
.classed('bar', true)
.style('height', function (d, i) {
return linear(d) - 20 + 'px';
})
.attr('x', function (d, i) {
return scaleBand(i)
})
.attr('width', function (d, i) {
return scaleBand.bandwidth() + 'px'
})
.attr('y', function (d, i) {
return 400 - linear(d) + 10;
});
上面是添加柱體的代碼,用到了enter,表示有多少數據添加多少rect。另外柱體的高度、寬度、x軸、y軸座標都動態生成。
container.selectAll('text').data(datalist)
.enter()
.append('text')
.attr('text-anchor', 'middle')
.text(function (d) {
return d;
})
.attr('x', function (d, i) {
return scaleBand(i) + scaleBand.bandwidth()/2 ;
})
.attr('y', function (d, i) {
return 400 - linear(d) + 30;
})
.style('fill', function (d) {
if (d > 30) {
return 'red'
}
})
上面是添加數據文字的代碼塊,再次用到enter,其中文字顏色fill屬性也由函數動態生成,大於30的部分是紅色。
最後附上完整代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
#app {
width: 500px;
height: 400px;
background: #efefef;
position: relative;
}
.bar {
/* width: 50px; */
fill: green;
position: absolute;
bottom: 100px;
}
.bar span {
display: block;
text-align: center;
}
</style>
</head>
<body>
<svg id="app">
</svg>
<script>
var datalist = [10, 20, 30, 40, 50,60,70,80,90]
//線性比例尺
const linear = d3.scaleLinear()
.domain([0, d3.max(datalist)])
.range([2, 398])
//序數比例尺
const scaleBand = d3.scaleBand().domain(d3.range(0,datalist.length))
.range([10, 490])
.paddingInner(0.08)
;
var container = d3.select("#app");
container.selectAll('rect')
.data(datalist)
.enter()
.append('rect')
.classed('bar', true)
.style('height', function (d, i) {
return linear(d) - 20 + 'px';
})
.attr('x', function (d, i) {
return scaleBand(i)
})
.attr('width', function (d, i) {
return scaleBand.bandwidth() + 'px'
})
.attr('y', function (d, i) {
return 400 - linear(d) + 10;
});
container.selectAll('text').data(datalist)
.enter()
.append('text')
.attr('text-anchor', 'middle')
.text(function (d) {
return d;
})
.attr('x', function (d, i) {
return scaleBand(i) + scaleBand.bandwidth()/2 ;
})
.attr('y', function (d, i) {
return 400 - linear(d) + 30;
})
.style('fill', function (d) {
if (d > 30) {
return 'red'
}
})
</script>
</body>
</html>
有任何問題歡迎評論或者私信提出~看到後我都會回覆😊