D3高级图形绘制

数据的海洋汹涌澎湃,其中有着不可计数的线索和彩虹。若要在波涛中捕捉这些光影,高级的图形绘制技术便是必备的舟桨。D3提供了强大的工具,以灵巧的指尖操纵数据,用精细的图形展现出来。这里,将介绍D3高级图形的绘制方法,为阅读者揭开绘画数据图谱的另一幅画卷。

力导向图(Force-Directed Graph)

力导向图是表现复杂关系网的理想选择,每个节点彼此吸引或排斥,形成一个动态的交互系统。

javascript 复制代码
var nodes_data = [
  {id: 'node1'}, {id: 'node2'}, {id: 'node3'}
];

var links_data = [
  {source: 'node1', target: 'node2'},
  {source: 'node2', target: 'node3'}
];

var simulation = d3.forceSimulation(nodes_data)
  .force('charge', d3.forceManyBody())
  .force('center', d3.forceCenter(150, 150))
  .force('link', d3.forceLink(links_data).id(d => d.id));

simulation.on('tick', function() {
  d3.select('svg')
    .selectAll('line')
    .data(links_data)
    .enter()
    .append('line')
    .attr('x1', d => d.source.x)
    .attr('y1', d => d.source.y)
    .attr('x2', d => d.target.x)
    .attr('y2', d => d.target.y);
});

此代码段使用D3力导向模拟器创建了节点间的吸引与排斥,绘制出了节点与连接线。

树图(Tree Graph)

树图能够体现层级数据的结构,让每一支数据枝节尽收眼底。

javascript 复制代码
var treeData = {
  name: "Root",
  children: [
    {name: "Branch1"},
    {name: "Branch2"}
  ]
};

var treeLayout = d3.tree().size([400, 200]);

var root = d3.hierarchy(treeData);
treeLayout(root);

var nodes = root.descendants();
var links = root.links();

d3.select('svg')
  .selectAll('.node')
  .data(nodes)
  .enter().append('circle')
  .classed('node', true)
  .attr('r', 5)
  .attr('cx', d => d.x)
  .attr('cy', d => d.y);

d3.select('svg')
  .selectAll('.link')
  .data(links)
  .enter().append('line')
  .classed('link', true)
  .attr('x1', d => d.source.x)
  .attr('y1', d => d.source.y)
  .attr('x2', d => d.target.x)
  .attr('y2', d => d.target.y);

上述代码构建了树图的布局,并绘制了节点及其连线。

地图绘制(Maps)

D3能够通过地理数据生成极其精确的地图,为乏味的数字赋予所在之地的生气。

javascript 复制代码
var projection = d3.geoMercator().center([107, 31]).scale(400);
var pathGenerator = d3.geoPath().projection(projection);

d3.json("china.geojson", function(error, data) {
  d3.select('svg')
    .selectAll('path')
    .data(data.features)
    .enter()
    .append('path')
    .attr('d', pathGenerator)
    .attr('fill', 'lightgrey')
    .attr('stroke', 'white');
});

在该段代码中,引用的地图数据文件 china.geojson 提供了地理信息,D3利用这些信息为每个行政区绘制了边界。

饼图(Pie Chart)

将饼图的各个切片着色,能够迅速传递部分与整体的关系。

javascript 复制代码
var pieData = [1, 2, 3, 4];

var pieGenerator = d3.pie();
var arc = d3.arc().innerRadius(0).outerRadius(100);

d3.select('svg')
  .selectAll('path')
  .data(pieGenerator(pieData))
  .enter()
  .append('path')
  .attr('d', arc)
  .attr('transform', 'translate(150,150)')
  .attr('fill', (d, i) => d3.schemeCategory10[i]);

此代码绘制了一个四色饼图,每个切片的大小与数据成比例。

堆叠图(Stacked Chart)

堆叠图将不同组的数据堆积起来,直观展现各部分之间的量度关系。

javascript 复制代码
var stackData = [
  {month: 'Jan', apples: 10, oranges: 5},
  {month: 'Feb', apples: 15, oranges: 10},
  {month: 'Mar', apples: 12, oranges: 8}
];

var stack = d3.stack().keys(['apples', 'oranges']);
var series = stack(stackData);

var color = d3.scaleOrdinal(d3.schemeCategory10);

d3.select('svg')
  .selectAll('g.series')
  .data(series)
  .enter().append('g')
  .classed('series', true)
  .style('fill', (d, i) => color(i))
  .selectAll('rect')
  .data(d => d)
  .enter().append('rect')
  .attr('x', d => xScale(d.data.month))
  .attr('y', d => yScale(d[1]))
  .attr('height', d => yScale(d[0]) - yScale(d[1]))
  .attr('width', xScale.bandwidth());

在此例中,每个月的苹果和橙子销量数据被顺序堆叠在一起,构成堆叠图的每一层。

散点图(Scatter Plot)

散点图通过标点在坐标轴上的位置,展示变量之间的关系。

javascript 复制代码
var scatterData = [{x: 30, y: 30}, {x: 70, y: 70}, {x: 110, y: 100}];

var xScale = d3.scaleLinear().domain([0, 130]).range([0, 400]);
var yScale = d3.scaleLinear().domain([0, 130]).range([400, 0]);

d3.select('svg')
  .selectAll('circle')
  .data(scatterData)
  .enter().append('circle')
  .attr('cx', d => xScale(d.x))
  .attr('cy', d => yScale(d.y))
  .attr('r', 5)
  .attr('fill', 'tomato');

这些标点的位置揭示了x和y两变量之间的相互作用。

热力图(Heatmap)

热力图以颜色的深浅来显示数值大小,使得数据热点一目了然。

javascript 复制代码
var heatmapData = [
  { day: 1, hour: 1, value: 10},
  { day: 2, hour: 1, value: 58},
  { day: 1, hour: 2, value: 30}
];

var colorScale = d3.scaleSequential(d3.interpolateInferno)
  .domain(d3.extent(heatmapData, d => d.value));

d3.select('svg')
  .selectAll('rect')
  .data(heatmapData)
  .enter().append('rect')
  .attr('x', d => xScale(d.hour))
  .attr('y', d => yScale(d.day))
  .attr('width', xScale.bandwidth())
  .attr('height', yScale.bandwidth())
  .attr('fill', d => colorScale(d.value));

热力图使热度如同火焰一般跃然纸上,暗藏的规律随之浮出水面。

箱线图(Boxplot)

箱线图展示了数据的分布情况,将中位数、四分位数及极值一览无余。

javascript 复制代码
var boxplotData = [10, 20, 30, 40, 50];

var chartWidth = 400, chartHeight = 400;

var y = d3.scaleLinear()
  .domain([0, 60])
  .range([chartHeight, 0]);

var boxplot = d3.box()
  .whiskers(iqr(1.5))
  .height(chartHeight)
  .domain(y.domain());

d3.select('svg')
  .data([boxplotData])
  .append('g')
  .call(boxplot);

此例中的箱线图利用四分位距规则界定了数据的主要离散范围。

矩阵布局(Treemap)

矩阵布局利用了空间,让数据的大小关系在几何形状的差异中表现出来。

javascript 复制代码
var treemapData = {
  "name": "Root",
  "children": [
    {"name": "Leaf A", "value": 30},
    {"name": "Leaf B", "value": 20},
    {"name": "Leaf C", "value": 50}
  ]
};

var treemapLayout = d3.treemap().size([400, 200]);

var root = d3.hierarchy(treemapData)
  .sum(d => d.value);

treemapLayout(root);

d3.select('svg')
  .selectAll('rect')
  .data(root.leaves())
  .enter().append('rect')
  .attr('x', d => d.x0)
  .attr('y', d => d.y0)
  .attr('width', d => d.x1 - d.x0)
  .attr('height', d => d.y1 - d.y0)
  .attr('fill', 'steelblue');

通过矩阵布局,每个叶子节点的面积与其数值成正比。

当数据遇见技术,便有了色彩斑斓的缤纷世界;而编织这幅图画的绘师,在数据的海洋中翱翔,用技术的羽翼折射出数据的鲜活与与众不同。高级图形绘制在D3的笔触之下,不再是简单的线条与色彩探索,而是深入数据的内在意义,从而描绘出让人心悦的数据风景画。

相关推荐
Martin -Tang10 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发11 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html