折線圖
折現圖可以使用svg折線元素polyline
來定義一組相連的直線段,但是更推薦使用d3.line()
和path
元素組合使用,這樣更加靈活。
d3.line()
構造一個新的線生成器,使用默認的.x
和.y
設置x,y訪問器函數。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="test-svg">
</div>
</body>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
window.onload = function() {
// 數據
var data = [{
date: new Date(2019, 3, 24),
value: 23.24
}, {
date: new Date(2019, 3, 25),
value: 72.15
}, {
date: new Date(2019, 3, 26),
value: 38.84
}, {
date: new Date(2019, 3, 27),
value: 58.62
}, {
date: new Date(2019, 3, 30),
value: 10.80
}, {
date: new Date(2019, 4, 1),
value: 85.47
}];
var width = 800,
height = 400,
padding = {
top: 40,
right: 40,
bottom: 40,
left: 40
};
var colors = d3.schemeSet2;
var svg = d3.select("#test-svg")
.append('svg')
.attr('width', width + 'px')
.attr('height', height + 'px');
// x軸:時間軸
var xScale = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return d.date;
}))
.range([padding.left, width - padding.right]);
var xAxis = d3.axisBottom()
.scale(xScale)
.tickSize(10);
svg.append('g')
.call(xAxis)
.attr("transform", "translate(0," + (height - padding.bottom) + ")")
.selectAll("text")
.attr("font-size", "10px")
.attr("dx", "50px");
// y軸
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.value;
})])
.range([height - padding.bottom, padding.top]);
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(10);
svg.append('g')
.call(yAxis)
.attr("transform", "translate(" + padding.left + ",0)");
var line = d3.line()
.x(function(d) {
return xScale(d.date);
})
.y(function(d) {
return yScale(d.value);
});
// 生成折線
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);
}
</script>
</html>
stroke-linecap
-
路徑兩端的形狀。
-
屬性值:butt | round | square | inherit
stroke-linejoin
-
路徑的轉角處使用的形狀
-
屬性值:miter | round | bevel | inherit
餅圖
- 餅圖一般使用餅布局
d3.pie()
和弧線生成器d3.arc()
來繪制。
餅布局d3.pie()
// 生成餅布局
var pie = d3.pie().value(function(d) {
return d.value;
})(data);
-
startAngle
:弧起始角度(角度跨度默認為2π ≈6.283185307179586) -
endAngle
:弧結束角度 -
padAngle
:弧之間的間隔 -
value
:數值
弧線生成器d3.arc()
一般來說有四種情況:
-
圓形:內圓半徑為0,外圓半徑大於0,且圓的弧度大於等於2π。會生成一個以外圓半徑為半徑的圓
-
扇形:內圓半徑為0,外圓半徑大於0,且圓的弧度小於2π。會生成一個以外圓半徑為半徑的扇形
-
環形:內圓半徑大於0,外圓半徑大於0,且圓的弧度大於等於2π。會生成一個環形
-
環形扇區:內圓半徑大於0,外圓半徑大於0,且圓的弧度小於2π。會生成一個環形扇區
圓形餅圖
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="test-svg">
</div>
</body>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
window.onload = function() {
// 數據
var data = [{
value: 335,
name: '直接訪問'
}, {
value: 310,
name: '郵件營銷'
}, {
value: 234,
name: '聯盟廣告'
}, {
value: 135,
name: '視頻廣告'
}, {
value: 1548,
name: '搜索引擎'
}];
var width = 400,
height = 400,
padding = {
top: 40,
right: 40,
bottom: 40,
left: 40
};
var colors = d3.schemeSet2;
var svg = d3.select("#test-svg")
.append('svg')
.attr('width', (width * 2) + 'px')
.attr('height', (height * 2) + 'px');
// 生成餅布局
var pie = d3.pie().value(function(d) {
return d.value;
})(data);
var radius = Math.min(width, height);
/*
* 弧線生成器
* .innerRadius 內圓半徑
* .outerRadius 外圓半徑
* .centroid 計算弧的中心
*/
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius / 2);
// 一個更大的圓弧,用來獲取標注線外圈的坐標
var outArc = d3.arc()
.innerRadius(radius / 2)
.outerRadius(radius);
var line = d3.line()
.x(function(d) {
return d[0];
})
.y(function(d) {
return d[1];
});
// 獲取標注線的點數據
var getLabelLine = function(d, type) {
var startPos = d.startAngle + (d.endAngle - d.startAngle) / 2;
var data = [];
var ra = (type === "text") ? 2.5 : 1;
data.push(arc.centroid(d));
data.push(outArc.centroid(d));
data.push({
0: outArc.centroid(d)[0] + (40 * (startPos < Math.PI ? 1 : -ra)),
1: outArc.centroid(d)[1]
});
return data;
}
var containers = svg.append("g")
.attr("transform", "translate(" + height + "," + height + ")");
var container = containers.selectAll("g")
.data(pie)
.join("g");
// 繪制餅圖
container.append("path")
.attr("stroke", "white")
.attr("d", arc)
.attr("fill", function(d, i) {
return colors[i];
});
// 繪制標注線
container.append("path")
.datum(function(d) {
return getLabelLine(d, "path");
})
.attr("class", "tips")
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);
// 繪制標注線上文字
container.append("text")
.datum(function(d) {
d.pos = getLabelLine(d, "text")[2];
return d;
})
.text(function(d) {
return d.data.name;
})
.attr("dx", function(d) {
return d.pos[0]
})
.attr("dy", function(d) {
return d.pos[1]
});
}
</script>
</html>
扇形餅圖
var pie = d3.pie().startAngle(0).endAngle(Math.PI).value(function(d) {
return d.value;
})(data);
var radius = Math.min(width, height);
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius / 2);
環形餅圖
var pie = d3.pie().value(function(d) {
return d.value;
})(data);
var radius = Math.min(width, height);
var arc = d3.arc()
.innerRadius(radius / 4)
.outerRadius(radius / 2);
環形扇區餅圖
var pie = d3.pie().startAngle(0).endAngle(Math.PI).value(function(d) {
return d.value;
})(data);
var radius = Math.min(width, height);
var arc = d3.arc()
.innerRadius(radius / 4)
.outerRadius(radius / 2);