用D3.js实现交互式地理信息图,核心思路是加载地理边界数据,利用投影把经纬度变成屏幕坐标,再用SVG路径绘制地图,最后绑定事件实现悬停、点击等交互。下面先说明整体步骤并给出可运行示例。
一、准备数据与引入库
地理信息图通常依赖GeoJSON格式描述区域边界。可以从公开资源获取世界或某地区的GeoJSON文件。页面中通过script标签引入D3.js即可。
基础HTML结构
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>D3地理信息图</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <div id="map"></div> <script src="app.js"></script> </body> </html>
二、设置投影与路径生成器
D3提供了多种地理投影,如geoMercator适合普通平面地图。用d3.geoPath()将投影后的坐标转为SVG的d属性。
初始化地图绘制
// 选择容器并设置SVG尺寸
const width = 800;
const height = 500;
const svg = d3.select('#map')
.append('svg')
.attr('width', width)
.attr('height', height);
// 创建墨卡托投影
const projection = d3.geoMercator()
.scale(120)
.translate([width / 2, height / 2]);
// 路径生成器
const path = d3.geoPath().projection(projection);
// 加载GeoJSON并绘制
d3.json('https://ipipp.com/data/countries.geojson').then(function(geoData) {
svg.selectAll('path')
.data(geoData.features)
.enter()
.append('path')
.attr('d', path)
.attr('fill', '#ccc')
.attr('stroke', '#333');
});
三、添加交互效果
交互式体验离不开事件绑定。常用的是鼠标悬停高亮与点击提示信息。
悬停与点击事件
svg.selectAll('path')
.data(geoData.features)
.enter()
.append('path')
.attr('d', path)
.attr('fill', '#ccc')
.attr('stroke', '#333')
.on('mouseover', function(event, d) {
d3.select(this).attr('fill', '#f00');
})
.on('mouseout', function(event, d) {
d3.select(this).attr('fill', '#ccc');
})
.on('click', function(event, d) {
alert('你点击了: ' + d.properties.name);
});
四、增强交互:缩放与平移
当地图区域较小时,可以引入d3.zoom()让用户自由缩放查看细节。
启用缩放行为
const g = svg.append('g');
// 将路径绘制到g分组中
g.selectAll('path')
.data(geoData.features)
.enter()
.append('path')
.attr('d', path)
.attr('fill', '#ccc')
.attr('stroke', '#333');
// 定义缩放
const zoom = d3.zoom()
.scaleExtent([1, 8])
.on('zoom', function(event) {
g.attr('transform', event.transform);
});
svg.call(zoom);
五、小结
通过上述步骤,我们完成了用D3.js加载地理数据、绘制SVG地图并添加悬停、点击与缩放交互的过程。实际项目中可结合后台接口动态更新数据,或用<code>d3.scaleSequential</code>做分级色彩映射,让地理信息图更具表现力。