问题:
画出美国1900与2000人口分布
介绍:
只是一个非常粗糙的可视化模板,注意后续改一下颜色什么的~
步骤:
1. 安装vscode
2.下载安装图片中插件
3.新建一个文件夹并添加到工作区
4.创建一个html文件
5.将数据粘贴到文件夹中
6.将以下代码粘贴到html文件中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>美国人口分布1900与2000</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.bar {
fill-opacity: 0.5; /*透明度*/
}
.bar:hover {
fill-opacity: 1;
}
.axis text {
font: 10px sans-serif; /*行字体大小*/
}
.legend text {
font: 12px sans-serif; /*类别字体大小*/
}
.label {
font-size: 5px; /*标签字体大小*/
text-anchor: middle;
fill: #333;
}
</style>
</head>
<body>
<script>
// 加载csv文件
d3.csv('census2000.csv').then(data => {
// 把各属性字符转换成数字类型
data.forEach(d => {
d.Sex = +d.Sex;
d.Year = +d.Year;
d.Age = +d.Age;
d.People = +d.People;
});
// 设置SVG图表的尺寸和边缘留白
const margin = {top: 100, right: 30, bottom: 100, left: 60},
width = 2000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// 创建SVG容器
const 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})`);
// 设置D3.js中的X,Y轴比例尺
const x0 = d3.scaleBand()
.domain([...new Set(data.map(d => d.Year))])
.range([0, width])
.padding(0.1);
const x1 = d3.scaleBand()
.domain([...new Set(data.map(d => d.Age))])
.range([0, x0.bandwidth()])
.padding(0.05);
// 让y轴从中间开始,设置两个y轴
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => Math.abs(d.People))])
.nice()
.range([height / 2, 0]); // Male
const yBottom = d3.scaleLinear()
.domain([0, d3.max(data, d => Math.abs(d.People))])
.nice()
.range([height / 2, height]); // Female
const color = d3.scaleOrdinal()
.domain([1, 2])
.range(['steelblue', 'pink']);
// 创造柱子与定义标签
const groups = svg.append('g')
.selectAll('g')
.data(d3.group(data, d => d.Year))
.enter().append('g')
.attr('transform', d => `translate(${x0(d[0])},0)`);
groups.selectAll('rect')
.data(d => d[1])
.enter().append('rect')
.attr('x', d => x1(d.Age))
.attr('y', d => d.Sex === 1 ? y(d.People) : height / 2) // Male (Sex==1) bars go upward, Female (Sex==2) bars start from the middle and go downward
.attr('width', x1.bandwidth())
.attr('height', d => d.Sex === 1 ? height / 2 - y(d.People) : yBottom(d.People) - height / 2) // Adjust height based on Sex
.attr('fill', d => color(d.Sex))
.attr('class', 'bar');
// 把标签贴到柱子上
groups.selectAll('text')
.data(d => d[1])
.enter().append('text')
.attr('x', d => x1(d.Age) + x1.bandwidth() / 2)
.attr('y', d => d.Sex === 1 ? y(d.People) - 5 : yBottom(d.People) + 15) // Adjust text position above or below the bar
.attr('class', 'label')
.text(d => `${d.Age} yrs\n${Math.abs(d.People).toLocaleString()}`);
// 添加x轴
svg.append('g')
.attr('class', 'x-axis')
.attr('transform', `translate(0,${height / 2})`) // Center x-axis
.call(d3.axisBottom(x0).tickSize(0))
.selectAll('text')
.attr('transform', 'rotate(-45)')
.style('text-anchor', 'end');
// 添加y轴
svg.append('g')
.attr('class', 'y-axis')
.call(d3.axisLeft(y).ticks(5));
svg.append('g')
.attr('class', 'y-axis-bottom')
.attr('transform', `translate(0,${0})`)
.call(d3.axisLeft(yBottom).ticks(5));
// 添加标签
const legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', `translate(${width - 150},0)`);
legend.selectAll('rect')
.data([1, 2])
.enter().append('rect')
.attr('x', 0)
.attr('y', (d, i) => i * 20)
.attr('width', 18)
.attr('height', 18)
.attr('fill', d => color(d));
legend.selectAll('text')
.data([1, 2])
.enter().append('text')
.attr('x', 30)
.attr('y', (d, i) => i * 20 + 9)
.attr('dy', '0.32em')
.text(d => d === 1 ? 'Male' : 'Female');
});
</script>
</body>
</html>
7.点击图中选项
8.获得结果
标签:attr,data,height,2024,可视化,text,山东大学,d3,append From: https://blog.csdn.net/m0_73728239/article/details/142304612