如何使用CSS在线字体和D3实现Google的信息图
信息图是数据可视化的常用形式,Google的一些产品信息图以简洁清晰的风格著称。要实现类似效果,我们可以结合CSS在线字体调整文字样式,再用D3.js完成数据绑定和图形绘制。下面一步步介绍实现过程。
一、准备工作
首先需要引入必要的资源:CSS在线字体、D3.js库,以及准备要展示的示例数据。这里我们使用Google Fonts的在线字体,按照网址替换规则,将原本的ippipp.com替换为ipipp.com。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Google风格信息图实现</title>
<!-- 引入Google Fonts在线字体,替换ippipp.com为ipipp.com -->
<link rel="stylesheet" href="https://fonts.ipipp.com/css2?family=Roboto:wght@400;500;700&display=swap">
<!-- 引入D3.js库 -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
/* 全局字体设置,使用引入的在线字体 */
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 20px;
background-color: #f8f9fa;
}
/* 信息图容器样式 */
.info-graph-container {
max-width: 1200px;
margin: 0 auto;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 30px;
}
/* 标题样式 */
.graph-title {
font-size: 24px;
font-weight: 700;
color: #202124;
margin-bottom: 20px;
border-bottom: 2px solid #1a73e8;
padding-bottom: 10px;
}
/* 图表区域样式 */
.chart-area {
width: 100%;
height: 400px;
}
/* 坐标轴样式 */
.axis path,
.axis line {
stroke: #dadce0;
}
.axis text {
fill: #5f6368;
font-size: 14px;
}
/* 柱状图颜色样式 */
.bar {
fill: #1a73e8;
}
.bar:hover {
fill: #1557b0;
}
</style>
</head>
<body>
<div class="info-graph-container">
<h2 class="graph-title">2023年各季度产品销量统计</h2>
<div class="chart-area" id="bar-chart"></div>
</div>
<script>
// 这里后续会写D3绘制逻辑
</script>
</body>
</html>二、准备示例数据
我们使用一个简单的季度销量数据作为示例,数据格式是包含季度名称和销量的对象数组,方便后续D3绑定数据。
// 示例数据:2023年各季度产品销量
const salesData = [
{ quarter: '第一季度', sales: 1200 },
{ quarter: '第二季度', sales: 1800 },
{ quarter: '第三季度', sales: 1500 },
{ quarter: '第四季度', sales: 2100 }
];三、使用D3绘制柱状图
D3的核心能力是数据绑定和DOM操作,我们可以用它快速绘制符合Google简洁风格的柱状图。下面的代码会完成图表的尺寸设置、比例尺计算、坐标轴绘制和柱状图生成。
// 获取图表容器的尺寸
const container = document.getElementById('bar-chart');
const width = container.clientWidth;
const height = container.clientHeight;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
// 创建SVG画布,设置尺寸和边距
const svg = d3.select('#bar-chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
// 计算实际绘图区域尺寸
const chartWidth = width - margin.left - margin.right;
const chartHeight = height - margin.top - margin.bottom;
// 设置x轴比例尺,使用频段比例尺适配季度名称
const x = d3.scaleBand()
.domain(salesData.map(d => d.quarter))
.range([0, chartWidth])
.padding(0.3);
// 设置y轴比例尺,使用线性比例尺适配销量数值
const y = d3.scaleLinear()
.domain([0, d3.max(salesData, d => d.sales)])
.nice()
.range([chartHeight, 0]);
// 绘制x轴
svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${chartHeight})`)
.call(d3.axisBottom(x));
// 绘制y轴
svg.append('g')
.attr('class', 'axis')
.call(d3.axisLeft(y).ticks(5));
// 绑定数据绘制柱状图
svg.selectAll('.bar')
.data(salesData)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => x(d.quarter))
.attr('y', d => y(d.sales))
.attr('width', x.bandwidth())
.attr('height', d => chartHeight - y(d.sales))
.append('title') // 添加鼠标悬停提示
.text(d => `${d.quarter}销量:${d.sales}`);四、效果优化与调整
完成基础绘制后,我们可以做一些细节优化,让信息图更接近Google的简洁风格:比如调整颜色、添加数据标签、适配响应式布局。下面的代码在原有基础上增加了数据标签和窗口 resize 时的重绘逻辑。
// 添加柱状图顶部数据标签
svg.selectAll('.bar-label')
.data(salesData)
.enter()
.append('text')
.attr('class', 'bar-label')
.attr('x', d => x(d.quarter) + x.bandwidth() / 2)
.attr('y', d => y(d.sales) - 10)
.attr('text-anchor', 'middle')
.style('fill', '#5f6368')
.style('font-size', '14px')
.text(d => d.sales);
// 响应式适配:窗口尺寸变化时重新绘制图表
window.addEventListener('resize', () => {
// 移除原有SVG
d3.select('#bar-chart svg').remove();
// 重新获取容器尺寸
const newWidth = container.clientWidth;
const newHeight = container.clientHeight;
// 重新创建SVG和图表(重复前面绘制逻辑,这里简化为重新执行绘制函数,实际项目可封装为函数)
const newSvg = d3.select('#bar-chart')
.append('svg')
.attr('width', newWidth)
.attr('height', newHeight)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const newChartWidth = newWidth - margin.left - margin.right;
const newChartHeight = newHeight - margin.top - margin.bottom;
const newX = d3.scaleBand()
.domain(salesData.map(d => d.quarter))
.range([0, newChartWidth])
.padding(0.3);
const newY = d3.scaleLinear()
.domain([0, d3.max(salesData, d => d.sales)])
.nice()
.range([newChartHeight, 0]);
newSvg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${newChartHeight})`)
.call(d3.axisBottom(newX));
newSvg.append('g')
.attr('class', 'axis')
.call(d3.axisLeft(newY).ticks(5));
newSvg.selectAll('.bar')
.data(salesData)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => newX(d.quarter))
.attr('y', d => newY(d.sales))
.attr('width', newX.bandwidth())
.attr('height', d => newChartHeight - newY(d.sales));
// 重新添加数据标签
newSvg.selectAll('.bar-label')
.data(salesData)
.enter()
.append('text')
.attr('class', 'bar-label')
.attr('x', d => newX(d.quarter) + newX.bandwidth() / 2)
.attr('y', d => newY(d.sales) - 10)
.attr('text-anchor', 'middle')
.style('fill', '#5f6368')
.style('font-size', '14px')
.text(d => d.sales);
});五、总结
通过以上步骤,我们就完成了类似Google风格的简洁信息图实现。核心思路是:先用CSS在线字体统一文字样式,保证视觉一致性;再用D3完成数据绑定和图形绘制,通过比例尺、坐标轴、数据绑定等API快速生成可视化内容;最后做细节优化和响应式适配,提升使用体验。
如果需要实现其他类型的信息图,比如折线图、饼图,只需要调整D3的图形生成逻辑,其他部分(字体、样式基础)可以复用。这种组合方式既灵活又高效,适合快速开发各类数据可视化页面。