// 获取当前节点
const findCurrentNode = useCallback((childrenNodes, name) => {
if (childrenNodes && !_.isEmpty(childrenNodes)) {
const nodeItem = _.find(childrenNodes, node => node.name === name);
if (nodeItem) {
return nodeItem;
}
const leaves = _.map(childrenNodes, node => {
const leaveNode = findCurrentNode(node.children, name);
return leaveNode ? leaveNode : null;
});
return _.get(_.compact(leaves), '[0]');
}
return null;
}, []);
// 富文本配置
const richLabel = useCallback((splitFeature, id, treeData, style) => ({
formatter: [
`{splitFeature|${splitFeature ? splitFeature : '\n'}}`,
`{name|${id}}`,
`${treeData ? `{icon|${style}}` : ''}`
].join('\n'),
rich: {
splitFeature: {
fontSize: 10,
color: '#666',
verticalAlign: 'middle',
padding: [-10, 0, 0, 0],
lineHeight: splitFeature ? 45 : (treeData ? 33 : 26)
},
name: {
fontSize: 12,
color: '#333',
lineHeight: splitFeature ? 31 : (treeData ? 31 : 30)
},
icon: {
fontSize: style === '^' ? 28 : 20,
width: 20,
height: 30,
lineHeight: 20,
color: '#999',
rotate: -90,
backgroundColor: id === 10 ? '#f5f5f5' : '#fff',
verticalAlign: 'bottom',
align: 'center',
padding: style === '^' ? [-10, 0, 0, 0] : [-4, 0, -6, 0],
borderRadius: 15,
borderWidth: 1,
borderColor: '#ccc'
}
}
}), []);
// 节点点击事件
const handleClickNode = useCallback(params => {
const charts = chartInstance.current;
const currentNodeName = params.data.name;
const nodes = _.get(charts, '_chartsViews[0]._data.tree._nodes');
// 点击改变icon
const tempData = options.series[0].data[0];
const currentNodeItem = _.find(nodes, ({name, depth}) => {
const nodeName = name ? name : 0;
return nodeName === currentNodeName && depth !== 0;
});
const {isExpand: currentExpand} = currentNodeItem;
const iconStyle = currentExpand ? 'v' : '^';
if (tempData.name === currentNodeName) {
tempData.label = richLabel(null, currentNodeName, tempData.children, iconStyle);
tempData.collapsed = !currentExpand;
}
else {
const currentNode = findCurrentNode(tempData.children, currentNodeName);
const {splitFeature: currentSplitFeature, name: currentName, children: currentChildren} = currentNode;
currentNode.label = richLabel(
currentSplitFeature, currentName, currentChildren, iconStyle
);
currentNode.collapsed = !currentExpand;
}
charts.setOption(options, {noMerge: true});
}, [options, chartInstance, treeData, richLabel, findCurrentNode]);
- 高亮决策路径,即高亮显示从顶层节点到当前节点的路径
// 鼠标移入移出事件
const handleMouseNode = useCallback((params, eventType) => {
const {name: currentNodeName, impurity, gain, sampleCount} = params.data;
const isMouseover = eventType === 'mouseover';
// 高亮决策路径的节点
const charts = chartInstance.current;
const nodes = _.get(charts, '_chartsViews[0]._data.tree._nodes');
_.forEach(nodes, node => {
const {name, hostTree} = node;
const nodeName = name ? name : 0;
if (nodeName === currentNodeName) {
_.forEach(getPathData(node, [node.dataIndex], 'dataIndex'), dataIndex => {
charts.dispatchAction({
type: isMouseover ? 'highlight' : 'downplay',
dataIndex
});
});
}
});
}, [chartInstance, getPathData, findCurrentNode]);
- 实现展开/收起全部节点,利用echarts.registerAction注册一个自定义的事件,然后再利用echartsInstance.dispatchAction去触发
// 全部展开/收起
const handleExpand = useCallback(e => {
// echarts实例
const charts = chartInstance.current;
const isExpand = e.target.innerText === '全部展开';
charts.dispatchAction({type: 'expandAll', expand: isExpand});
}, [chartInstance, showExpand, hideExpand]);
useEffect(() => {
// 注册全部展开/收起事件
echarts.registerAction({
type: 'expandAll',
event: 'expandAll'
}, (payload, ecModel) => {
ecModel.eachComponent(
{mainType: 'series', subType: 'tree', query: payload},
seriesModel => {
const tree = seriesModel.getData().tree;
_.forEach(tree._nodes, node => {
node.isExpand = node.depth < DEFAULT_DEPTH ? payload.expand : false;
});
}
);
});
}, [options]);