如何用D3.js按键值占比为旭日图非叶节点生成加权混合色
D3 旭日图非叶节点加权混合色实现方案
核心实现逻辑
你需要通过逐通道加权平均的方式生成混合色,完全匹配权重占比规则,具体实现代码如下:
第一步:封装加权混色工具函数
function getWeightedMixedColor(mimeTypes, colorScale) { // 计算总权重 const totalWeight = Object.values(mimeTypes).reduce((sum, count) => sum + count, 0); let r = 0, g = 0, b = 0; // 遍历所有mime类型,逐通道累加加权值 for (const [mime, count] of Object.entries(mimeTypes)) { const weight = count / totalWeight; const rgb = d3.rgb(colorScale(mime)); r += rgb.r * weight; g += rgb.g * weight; b += rgb.b * weight; } // 返回合法RGB颜色值 return d3.rgb(Math.round(r), Math.round(g), Math.round(b)).hex(); }
如果对色彩均匀度要求更高,可将RGB转换为Lab色彩空间计算:把
d3.rgb(colorScale(mime))替换为d3.lab(colorScale(mime)),累加l、a、b通道后再转回RGB即可,避免Gamma校正带来的偏色问题。
第二步:集成到旭日图填充逻辑
在旭日图的fill属性绑定逻辑中,区分叶节点和非叶节点处理:
// 旭日图弧填充设置 path.attr('fill', d => { // 叶节点直接返回对应MIME类型颜色 if (d.children === undefined || d.children.length === 0) { return myColor(d.data.mime_type); // 这里替换为你叶节点存储MIME类型的字段 } // 非叶节点返回加权混合色 return getWeightedMixedColor(d.data.mime_types, myColor); })
效果验证
以你给出的示例mime_types统计值为例:
总权重为 1+49+13+47+5+3+4+58 = 180text/plain权重占比约32%,application/x-executable占比约27%,application/x-sharedlib占比约26%,三类高占比MIME的颜色会主导混合结果,占比仅0.5%的application/octet-stream只会对最终颜色产生极微弱影响,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Joe Jonah
相关产品推荐
相关产品推荐

