D3.js v4:从含数组的节点值创建过滤函数,提取独立职业值
解决D3.js中多职业节点的过滤与唯一值提取问题
嘿,刚上手D3.js遇到这种数组和字符串混合的字段处理很正常,我来帮你搞定这个职业提取和过滤的问题~
问题核心
你的节点数据里,occupation字段有的是字符串(比如"agent"),有的是数组(比如["physician", "govenor"]),直接用d3.map或者nest会把数组当成一个整体转换成逗号分隔的字符串,自然没法拆成独立的职业值。
提取唯一职业值的解决方案
我们可以分两步走:先把所有职业展开成单个值的数组,再去重得到唯一列表:
- 展开所有职业项
用flatMap遍历节点,把数组类型的occupation拆成单个元素,字符串类型的则包装成数组(包括undefined的情况):
// 从你的graph数据中提取所有职业项 const allOccupations = graph.nodes.flatMap(d => { return Array.isArray(d.occupation) ? d.occupation : [d.occupation]; });
这一步之后,allOccupations会变成:["agent", undefined, "physician", "emir", "physician", "govenor", undefined]
- 去重得到唯一值列表
用ES6的Set来自动去重,再转回数组:
const uniqueOccupations = [...new Set(allOccupations)];
最终就能得到你想要的结果:["agent", undefined, "physician", "emir", "govenor"]
拓展:根据职业高亮节点
如果要实现点击某个职业后高亮对应节点的功能,可以这样写判断逻辑:
function highlightNodes(targetOccupation) { // 遍历所有节点,判断是否包含目标职业 graph.nodes.forEach(node => { // 统一把职业转成数组格式,方便判断 const nodeOccupations = Array.isArray(node.occupation) ? node.occupation : [node.occupation]; // 判断是否匹配 const isMatched = nodeOccupations.includes(targetOccupation); // 这里替换成你的节点选择器和高亮样式 d3.select(`[data-node-id="${node.id}"]`) .style("opacity", isMatched ? 1 : 0.2) // 匹配的节点全透明度,不匹配的半透明 .style("stroke", isMatched ? "#ff4444" : "#333"); // 匹配的节点加红色边框 }); }
这样不管节点是单个职业还是多个职业,都能正确判断啦~
内容的提问来源于stack exchange,提问作者wsalesky
相关产品推荐
相关产品推荐

