
本文详解如何在 D3.js v3 环境下正确实现太阳图(Sunburst)的颜色映射,解决 d3.scaleOrdinal is not a function 报错及全黑切片问题,提供可直接运行的兼容代码与关键注意事项。
本文详解如何在 d3.js v3 环境下正确实现太阳图(sunburst)的颜色映射,解决 `d3.scaleordinal is not a function` 报错及全黑切片问题,提供可直接运行的兼容代码与关键注意事项。
在使用 D3.js v3 构建太阳图时,原示例中基于 D3 v4+ 的 API(如 d3.scaleOrdinal() 和 d3.schemePaired)会直接报错——因为这些特性在 v3 中根本不存在。d3.scaleOrdinal 是 D3 v4 引入的新型序数标度,而 d3.schemePaired 更是 v4.2 才加入的内置调色板。D3 v3 对应的等效方案是 d3.scale.category10() 或 d3.scale.category20(),它们返回的是函数式序数标度(ordinal scale),但调用方式和行为与 v4+ 有本质区别。
首先,需彻底清理 HTML 中冲突的 D3 版本引用。您当前同时引入了:
<script src="//unpkg.com/d3"></script><!-- 默认加载最新版(v7+) --><script src="http://d3js.org/d3.v3.min.js"></script><!-- 明确加载 v3 -->
这会导致后加载的 v3 覆盖部分全局 d3 对象,但 d3.scaleOrdinal 等新属性仍可能残留或引发不一致状态。务必只保留 v3 引用,并移除所有其他 D3 脚本标签:
<script src="https://d3js.org/d3.v3.min.js"></script><script src="https://unpkg.com/sunburst-chart@1.11.0"></script><style>body { margin: 0; }</style>
接着,重构颜色逻辑:D3 v3 的 d3.scale.category10() 返回一个接受字符串键并返回颜色的函数,但它不支持直接传入数组(如 d3.schemePaired)作为域(domain)。更重要的是,sunburst-chart 库在 v1.x 版本中已适配 D3 v3,其 .color() 方法期望接收一个函数,该函数接收节点数据 d 和父节点 parent,并返回 CSS 颜色值。
以下为完整、可运行的 v3 兼容代码:
<div id="chart"></div>
<script>
// ✅ D3 v3 兼容的颜色标度:使用 category20(20色,比category10更丰富)
var colorScale = d3.scale.category20();
// ✅ 构建颜色映射函数:根据父节点名称生成稳定颜色
// 注意:v3 中不能用 d3.schemePaired,需手动构造 domain 或依赖标度自动分配
var getColor = function(d, parent) {
var name = parent ? parent.data.name : 'root';
return colorScale(name); // 自动哈希 name → 稳定颜色
};
fetch('flare.json')
.then(function(res) { return res.json(); })
.then(function(data) {
Sunburst()
.data(data)
.label('name')
.size('size')
.color(getColor) // ✅ 传入函数,非调用结果
.tooltipContent(function(d, node) {
return 'Size: <i>' + node.value + '';
})
(document.getElementById('chart'));
});
</script>
⚠️ 关键注意事项:
-
不要写
d3.scale.category10(d3.schemePaired):d3.schemePaired在 v3 中未定义,会报undefined错误;且category10()不接受参数,直接调用即可。 -
.color()必须传入函数,而非函数调用结果:错误写法color(colorScale(...))会导致所有节点使用同一颜色(如黑色),因为标度被立即执行,未绑定到每个节点。 - 若需更高定制性(如固定某类名对应特定颜色),可显式设置标度域:
var names = ['flare', 'analytics', 'cluster', 'graph']; // 提前收集所有可能的父名 colorScale.domain(names); // 确保顺序与颜色一一对应
- 推荐使用
d3.scale.category20()而非category10():前者提供 20 种高对比度颜色,更适合多层级太阳图,避免颜色重复过早。
总结:D3 v3 与 v4+ 的生态差异要求开发者主动降级 API 使用习惯。核心原则是——弃用 scaleOrdinal / scheme*,拥抱 scale.category*() + 函数式 .color() 回调。只要版本引用纯净、标度使用得当,太阳图色彩即可准确、稳定、美观地渲染。










