From 3f25c9c0d5f6f48456df418beaa22d1f3d65e989 Mon Sep 17 00:00:00 2001 From: tiwarir Date: Tue, 7 Jul 2026 16:09:02 -0400 Subject: [PATCH] fix(tree): apply selected line style to edges. close #18214 --- src/chart/tree/TreeView.ts | 33 ++++++++- test/ut/spec/series/tree.test.ts | 115 +++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 test/ut/spec/series/tree.test.ts diff --git a/src/chart/tree/TreeView.ts b/src/chart/tree/TreeView.ts index c819e19716..e0fbe208c2 100644 --- a/src/chart/tree/TreeView.ts +++ b/src/chart/tree/TreeView.ts @@ -36,7 +36,14 @@ import GlobalModel from '../../model/Global'; import ExtensionAPI from '../../core/ExtensionAPI'; import { TreeNode } from '../../data/Tree'; import SeriesData from '../../data/SeriesData'; -import { setStatesStylesFromModel, setStatesFlag, setDefaultStateProxy, HOVER_STATE_BLUR } from '../../util/states'; +import { + setStatesStylesFromModel, + setStatesFlag, + setDefaultStateProxy, + HOVER_STATE_BLUR, + enterSelect, + leaveSelect +} from '../../util/states'; import { AnimationOption, ECElement, RoamPayload } from '../../util/types'; import tokens from '../../visual/tokens'; import { @@ -214,6 +221,8 @@ class TreeView extends ChartView { }) .execute(); + updateTreeEdgeSelection(seriesModel); + this._updateNodeAndLinkScale(seriesModel); if (seriesModel.get('expandAndCollapse') === true) { @@ -232,6 +241,18 @@ class TreeView extends ChartView { this._firstRender = false; } + select(seriesModel: TreeSeriesModel): void { + updateTreeEdgeSelection(seriesModel); + } + + unselect(seriesModel: TreeSeriesModel): void { + updateTreeEdgeSelection(seriesModel); + } + + toggleSelect(seriesModel: TreeSeriesModel): void { + updateTreeEdgeSelection(seriesModel); + } + __updateOnOwnRoam( payload: RoamPayload, seriesModel: TreeSeriesModel, @@ -323,6 +344,16 @@ function symbolNeedsDraw(data: SeriesData, dataIndex: number) { && !isNaN(layout.x) && !isNaN(layout.y); } +function updateTreeEdgeSelection(seriesModel: TreeSeriesModel) { + const data = seriesModel.getData(); + + data.eachItemGraphicEl(function (symbolEl: TreeSymbol, dataIndex) { + const edge = symbolEl.__edge; + if (edge) { + seriesModel.isSelected(dataIndex) ? enterSelect(edge) : leaveSelect(edge); + } + }); +} function updateNode( data: SeriesData, diff --git a/test/ut/spec/series/tree.test.ts b/test/ut/spec/series/tree.test.ts new file mode 100644 index 0000000000..4f4c664d08 --- /dev/null +++ b/test/ut/spec/series/tree.test.ts @@ -0,0 +1,115 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import { createChart, getECModel } from '../../core/utHelper'; +import { EChartsType } from '../../../../src/echarts'; +import Element from 'zrender/src/Element'; + + +describe('series/tree', function () { + + let chart: EChartsType; + + beforeEach(function () { + chart = createChart(); + }); + + afterEach(function () { + chart.dispose(); + }); + + function getDataIndex(name: string): number { + const data = getECModel(chart).getSeriesByIndex(0).getData(); + const dataIndex = data.indexOfName(name); + expect(dataIndex >= 0).toEqual(true); + return dataIndex; + } + + function getEdge(dataIndex: number): Element & { + selected?: boolean, + states?: { + select?: { + style?: { + stroke?: string + } + } + } + } { + const seriesModel = getECModel(chart).getSeriesByIndex(0); + const symbolEl = seriesModel.getData().getItemGraphicEl(dataIndex) as Element & { + __edge: Element + }; + return symbolEl.__edge; + } + + it('applies select.lineStyle to selected edges', function () { + const selectedColor = '#ff6600'; + + chart.setOption({ + series: [{ + type: 'tree', + selectedMode: 'single', + animation: false, + select: { + itemStyle: { + color: selectedColor + }, + lineStyle: { + color: selectedColor + } + }, + data: [{ + name: 'root', + children: [{ + name: 'child 1' + }, { + name: 'child 2' + }] + }] + }] + }); + + const childDataIndex = getDataIndex('child 1'); + const siblingDataIndex = getDataIndex('child 2'); + const childEdge = getEdge(childDataIndex); + const siblingEdge = getEdge(siblingDataIndex); + + expect(childEdge.states.select.style.stroke).toEqual(selectedColor); + expect(childEdge.selected).toEqual(false); + + chart.dispatchAction({ + type: 'select', + seriesIndex: 0, + dataIndex: childDataIndex + }); + + expect(childEdge.selected).toEqual(true); + expect(siblingEdge.selected).toEqual(false); + + chart.dispatchAction({ + type: 'select', + seriesIndex: 0, + dataIndex: siblingDataIndex + }); + + expect(childEdge.selected).toEqual(false); + expect(siblingEdge.selected).toEqual(true); + }); + +});