D3.js v4:基于含数组的节点值创建过滤函数的问题
解决D3.js中含数组的节点职业提取与过滤问题
嘿,刚接触D3.js就遇到这种嵌套数据的问题很正常,我来帮你捋清楚怎么搞定它!
你的核心问题是:有些节点的occupation是字符串,有些是数组,直接用d3.map或者nest会把数组转成逗号分隔的字符串,没法拆成单独的职业值。我们需要先把所有职业平铺成一维数组,再去重,就能得到你想要的唯一职业列表了。
第一步:提取并平铺所有职业
我们可以用JavaScript的flatMap方法(如果你的环境支持ES2019+),它能同时完成“映射”和“平铺数组”的操作,把单个字符串和数组统一处理成单个值的集合:
// 假设你的数据存在graph变量中 const allOccupations = graph.nodes.flatMap(d => { // 处理没有occupation的节点,返回"undefined" if (!d.occupation) return ['undefined']; // 如果是数组直接返回,否则把字符串包装成数组 return Array.isArray(d.occupation) ? d.occupation : [d.occupation]; });
如果你的D3版本比较旧(比如v5及以下),可以用d3.merge替代flatMap,效果一样:
const allOccupations = d3.merge(graph.nodes.map(d => { if (!d.occupation) return ['undefined']; return Array.isArray(d.occupation) ? d.occupation : [d.occupation]; }));
第二步:去重得到唯一职业列表
用ES6的Set来快速去重,再转回数组:
const uniqueOccupations = [...new Set(allOccupations)]; console.log(uniqueOccupations); // 输出正好是你想要的:["agent", "undefined", "physician", "emir", "govenor"]
延伸:用这个列表实现节点高亮过滤
既然你要做力导向图的职业高亮,这里给你补充一个过滤函数的示例,基于选中的职业来调整节点透明度:
function highlightByOccupation(selectedOccupation) { d3.selectAll('.node') // 假设你的节点类名为node .style('opacity', d => { // 统一把当前节点的职业转成数组格式 const nodeOccupations = d.occupation ? (Array.isArray(d.occupation) ? d.occupation : [d.occupation]) : ['undefined']; // 匹配则完全显示,否则变暗 return nodeOccupations.includes(selectedOccupation) ? 1 : 0.2; }); }
这样不管节点是单个职业还是多个职业数组,都能准确匹配啦~
内容的提问来源于stack exchange,提问作者wsalesky
相关产品推荐
相关产品推荐

