D3.js繪制基本圖形
d3.js 繪制基本圖形
最近開始學習d3.js 主要是,初步認識d3.js,並且運行D3.jsD3.js數據可視化(data visualization)環境.
因為之前沒有接觸郭d3,因為業務需求,需要繪制一系列的圖表,所以上來直接學習繪制,剛開始經過一天的簡單了解,懂得了d3繪制代碼的基本格式,然后開始搜索自己需要的圖形的基本模板,然后根據自己的 實際業務需求來進行基本的更改,這樣就需要我們對自己需要使用的代碼,全程了解,這樣我們就可以更加便捷的進行修改。下面是我最近三天自己繪制一些基本圖形的代碼:
這里注意:因為沒有認真的學習過d3知識,在繪制時,因為不同版本的方法使用不同,所以我在引入d3的時候,會同時插入兩個版本的d3,使用方法,
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>
1、條形圖
首先貼上完整的代碼進行展示:因為是是剛開始學習d3,所以代碼里都做了基本的注釋。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>條形圖</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>
<style>
.axis path,
.axis line{
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 15px;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
//1、定義寬高
var height = 600;
var width = 600;
//2、添加數據
var dataset= [30,20,45,12,21,28,46,64,73,78,54];
// var num = 15;
//設置刷新事件,當沒刷新一次數據變化一次,條形圖也隨之變化
// for(var i = 0; i < 4; i++){
// var tempnum = Math.floor(Math.random() * 50);
// dataset.push(tempnum);
// }
// console.log(dataset);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var xAxisScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, 500]);
var yAxisScale = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([500, 0]);
var xAxis = d3.svg.axis().scale(xAxisScale).orient("bottom");
var yAxis = d3.svg.axis().scale(yAxisScale).orient("left");
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0,500],0.05);
var yScale = d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([0,500]);
// 繪制矩形
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
// .on("click", function(){
// d3.select(this).attr("fill","black");
// }) // 添加點擊事件
.attr("x", function(d,i){
return 100 + xScale(i);
} )
.attr("y",function(d,i){
return 50 + 500 - yScale(d) ;
})
.attr("width", function(d,i){
return xScale.rangeBand();
})
.attr("height",yScale)
.attr("fill", "steelblue")
.transition()
.duration(2000)
.ease("bounce")
.delay(1000)
.attr("fill","red");
// 繪制文字標簽
svg.selectAll("text")
.data(dataset)
.enter().append("text")
.attr("x", function(d,i){
return 100 + xScale(i);
} )
.attr("y",function(d,i){
return 50 + 500 - yScale(d) ;
})
.attr("dx", function(d,i){
return xScale.rangeBand()/3;
})
.attr("dy", 15)
.attr("text-anchor", "begin")
.attr("font-size", 14)
.attr("fill","white")
.text(function(d,i){
return d;
});
// 在<svg>中添加元素<g>,g是svg標准中定義的元素,是分組的意思,用於把相關的元素進行組合的容器元素
// 將包含坐標軸的元素組合在一個group里call(xAxis),調用函數xAxis並設置執行上下文為元素<g>。
// attr("transform","translate(100, 550)")表示將x軸右移100px,並下移550px
svg.append("g")
.attr("class","axis")
.attr("transform","translate(100,550)")
.call(xAxis);
svg.append("g")
.attr("class","axis")
.attr("transform","translate(100,50)")
.call(yAxis);
</script>
</body>
</html>
下面是圖形展示:大家可以根據自己的需求,來進行代碼的更改。
2、折線圖
代碼展示:
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
.line {
fill: none;
stroke: #ffab00;
stroke-width: 3;
}
/* .dot {
fill: #ffab00;
stroke: #fff;
} */
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
//1、定義寬高
var margin = {top: 50, right: 50, bottom: 50, left: 50};
// var width = window.innerWidth - margin.left - margin.right ; // Use the window's width
// var height = window.innerHeight - margin.top - margin.bottom ;
var width = 400 - margin.left - margin.right ;
var height = 400 - margin.top - margin.bottom ;
// 把svg添加到頁面並使用
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//2、初始化數據
var dataset = [{'y':0.2},{'y':0.2},{'y':0.4},{'y':0.5},{'y':0.55},{'y':0.5}] //d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
// 3、比例尺
var xScale = d3.scaleLinear()
.domain([0, dataset.length-1])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, 1])
.range([height, 0]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale)); // 使用d3.axisBottom創建axis組件
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale)); // 創建一個帶有d3.axisLeft的axis組件
//4、繪制直線
var line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.y); })
// .curve(d3.curveBasis) // 對折線進行平滑處理
// 5. 追加路徑、綁定數據並調用行生成器
svg.append("path")
.datum(dataset) // 10. Binds data to the line
.attr("class", "line") // Assign a class for styling
.attr("d", line); // 11. Calls the line generator
//6. 為每個數據點追加一個圓
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("class", "dot") // 為樣式分配一個類
.attr("cx", function(d, i) { return xScale(i) })
.attr("cy", function(d) { return yScale(d.y) })
.attr("r", 4)
.attr("stroke", "#5E5E5E")
.attr("stroke-width", 2)
.attr('fill',"none");
</script>
</body>
效果圖展示:
3、散點圖
代碼展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3-coordinate-test</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
/* .cocoordinate-div {
margin: 100px 500px 100px;
border: 2px solid blue;
} */
.title {
font-size: 26px;
font-family: 'Microsoft YaHei';
fill: red;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: 'Microsoft YaHei';
font-size: 12px;
}
</style>
</head>
<body>
<script>
//1、設置寬高
var Width = 800;
var Height = 400;
var padding = 60;
//2、數據初始化
var dataset = [
[0, 0], [65.66, 420], [520, 260], [360, 320], [200, 200],
[130, 623], [652, 52], [333, 666], [729, 656], [134, 352],
[120, 56], [905, 177], [777, 888], [1200, 1000]
];
var svg = d3.select('body') //創建SVG
.append('svg')
.attr('width', Width)
.attr('height', Height);
// 3、設置標題
svg.append('text')
.attr('x', Width / 2 - 120)
.attr('y', 30)
.attr('class', 'title') //title定義樣式屬性
.text('這是一個用d3畫的簡略坐標軸');
// 4、創建比例尺
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d[0]; })])
.range([padding, Width - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d[1]; })])
.range([Height - padding, padding]);
var rScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d[1]; })])
.range([2, 4]);
// 5、設置散點的坐標, 半徑
svg.selectAll('circle')
.data(dataset)
.enter().append('circle')
.attr('cx', function(d) {
return xScale(d[0]); })
.attr('cy', function(d) {
return yScale(d[1]); })
.attr('r', function(d) {
return rScale(d[1]);
});
// 6、設置文本
svg.selectAll('text')
.data(dataset)
.enter().append('text')
.text(function(d) {
return '(' + d[0] + ', ' + d[1] + ')'; })
.attr('x', function(d) {
// 設置偏移量,讓文本位於上方
return xScale(d[0]) - 20; })
.attr('y', function(d) {
return yScale(d[1]) - 10; })
.attr('font-family', 'Microsoft YaHei')
.attr('font-size', '12px')
.attr('fill', '#9400D3');
//7、繪制坐標軸
// 設置精度和樣式
var formatPrecision = d3.format('$');
var xAxis = d3.svg.axis() // 定義X軸
.scale(xScale)
.ticks(7) // 粗略的設置刻度線的數量,包括原點
.orient('bottom')
.tickFormat(formatPrecision);
var yAxis = d3.svg.axis() // 定義Y軸
.scale(yScale)
.orient('left')
.ticks(7)
.tickFormat(formatPrecision);
svg.append('g') // svg中: g元素是一個分組元素 創建X軸,
.attr('class', 'axis')
.attr('transform', 'translate(0, ' + (Height - padding) + ')')// 設置據下邊界的距離
.call(xAxis);
svg.append('g') // 創建Y軸
.attr('class', 'axis')
.attr('transform', 'translate(' + padding + ', 0)') // Y軸離左邊界的距離
.call(yAxis);
</script>
</body>
</html>
4、簡單堆棧圖
完整代碼展示:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<style>
.tick text {
font-size: 10px;
}
</style>
</head>
<body>
<script>
//1、定義寬高
const width = 500;
const height = 450;
const margin = { top: 25, right: 35, bottom: 100, left: 50 };
//2、確定初始數據
const data = [
{year:2005, value1:3000 ,value2:200 ,value3:0.06},
{year:2006, value1:1400 ,value2:40,value3:0.02},
{year:2007, value1:3800 ,value2:100,value3:0.03},
{year:2008, value1:4900 ,value2:70,value3:0.01},
{year:2009, value1:2000 ,value2:80,value3:0.04}
];
//3、堆棧圖顏色設置
const colors = ['orange', 'red']; //顏色分組
const groups = ['value1', 'value2']; //類別分組
const layout = d3.stack().keys(groups)(data);//用來生成一個以0到groups.length-1為主鍵的堆棧生成器
const svg = d3.select('body') //選擇body元素
.append('svg') //在body元素中添加svg
.attr('width', width + margin.left + margin.right) //設定<svg>的寬度屬性
.attr('height', height + margin.top + margin.bottom) //設定<svg>的高度屬性
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
//4、繪制坐標軸比例尺
const xScale = d3.scaleBand()
.padding(0.4) //設置條形圖的間隔
.domain(data.map(d => d.year)) //對條形圖的橫坐標進行映射
.range([0, width]);
const yMax = 6000;
const yScale = d3.scaleLinear()
.domain([0, yMax])
.range([height, 0]);
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale).ticks(10);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.selectAll('text')
// .attr('transform', 'rotate(-45)') //這是一個控制橫坐標字體斜體;
svg.append('g').call(yAxis);
// 5、開始繪制堆棧圖
//堆棧圖
svg
.selectAll('.group')
.data(layout)
.enter()
.append('g')
.attr('year', ({key}) => key)
.attr('fill', (d, i) => colors[i])
.selectAll('body')
.data(d => d)
.enter()
.append('rect')
.attr('x', ({data: {year}}) => xScale(year))
.attr('y', ([y, h]) => yScale(h))
.attr('width', xScale.bandwidth())
.attr('height', ([y, h]) => height - yScale(h - y));
</script>
</body>
運行結果展示:
5、帶有折線圖的堆棧圖:
完整代碼展示:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<style>
.tick text {
font-size: 10px;
}
.axis path,
.axis line{
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 8px;
}
</style>
</head>
<body>
<script>
//1、定義寬高
const margin = { top: 25, right: 35, bottom: 100, left: 50 };
const width = 500;
const height = 450;
//2、確定初始數據
const data = [
{year:2005, value1:3000 ,value2:200 ,value3:0.06},
{year:2006, value1:1400 ,value2:40,value3:0.02},
{year:2007, value1:3800 ,value2:100,value3:0.03},
{year:2008, value1:4900 ,value2:70,value3:0.01},
{year:2009, value1:2000 ,value2:80,value3:0.04}
];
const svg = d3.select('body') //選擇body元素
.append('svg') //在body元素中添加svg
.attr('width', width + margin.left + margin.right) //設定<svg>的寬度屬性
.attr('height', height + margin.top + margin.bottom) //設定<svg>的高度屬性
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
//3、堆棧圖顏色設置
const colors = ['#ff6633', '#CDAF95']; //顏色分組
const groups = ['value1', 'value2']; //類別分組
const layout = d3.stack().keys(groups)(data);//用來生成一個以0到groups.length-1為主鍵的堆棧生成器
//4、繪制坐標軸比例尺
//設置刻度格式
var formatAsPercentage = d3.format(".1%")
const xScale = d3.scaleBand()
.padding(0.4) //設置條形圖的間隔
.domain(data.map(d => d.year)) //對條形圖的橫坐標進行映射
.range([0, width]);
const yMax = 6000;
const yScale = d3.scaleLinear()
.domain([0, yMax])
.range([height, 0]);
const zMax=0.06;
const zScale = d3.scaleLinear()
.domain([0,zMax])
.range([height,0]);
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale).ticks(10);
const zAxis= d3.axisRight(zScale).ticks(10).tickFormat(formatAsPercentage);
svg.append('g') //橫坐標的顯示
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.selectAll('text')
// .attr('transform', 'rotate(-45)') //這是一個控制橫坐標字體斜體;
svg.append('g').call(yAxis);
svg.append('g').call(zAxis).attr("transform","translate("+width+",0)");
// 5、開始繪制堆棧圖
//堆棧圖
svg
.selectAll('.group')
.data(layout)
.enter()
.append('g')
.attr('year', ({key}) => key)
.attr('fill', (d, i) => colors[i])
.selectAll('body')
.data(d => d)
.enter()
.append('rect')
.attr('x', ({data: {year}}) => xScale(year))
.attr('y', ([y, h]) => yScale(h))
.attr('width', xScale.bandwidth())
.attr('height', ([y, h]) => height - yScale(h - y));
//6、開始繪制折線圖
var lineGen = d3.svg.line()
.x(function(d) {
//設置折線圖的偏移量,使折線點居中
return xScale(d.year)+xScale.bandwidth()/2;
})
.y(function(d) {
return zScale(d.value3);
});
svg.append('path')
.attr('d', lineGen(data))
.attr('stroke', '#ffcc33')
.attr('stroke-width', 3)
.attr('fill', 'none');
//為折線圖每個點坐標添加透明圓圈
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d.year)+xScale.bandwidth()/2+0.5;
})
.attr('cy', function(d) {
return zScale(d.value3)-1;
})
.attr('r', 3.5)
.attr('fill',"none")
.attr("stroke", "#5E5E5E")
.attr("stroke-width", 1);
</script>
</body>
運行結果展示:
這是在上一個堆棧圖的基礎上進行的修改,因為日常的需求中是需要我們對堆棧圖中的數據,通過折線圖的形式進行更加直觀的展示,折線圖可以看出數據的變化,這里這一橫坐標是年,年作為兩個圖形形式的同一個橫坐標,是我們在繪制雙圖形時,需要特別注意的地方。
https://blog.csdn.net/qq_39355295/article/details/87477442