echarts tree 树状图点击改变节点样式&高亮决策路径&全部展开和收起

4,866 阅读1分钟
  • 点击节点改变样式,利用富文本实现
// 获取当前节点
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]);