Skip to content

Commit 9994b01

Browse files
committed
[fix] Refactor label visibility logic and resolve review comments
- Moved backward compatibility logic (showLabelsAtZoomLevel -> showMapLabelsAtZoom) to NetJSONGraph constructor in core.js. - Refactored generateMapOption in render.js to remove redundant variables and use cleaner falsy checks. - Updated mouseover/mouseout handlers to evaluate zoom dynamically. - Removed redundant default value assignment in the render loop. - Updated render tests to reflect logic changes.
1 parent 9f53968 commit 9994b01

File tree

4 files changed

+29
-69
lines changed

4 files changed

+29
-69
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18

src/js/netjsongraph.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class NetJSONGraph {
3232
this.setupGraph();
3333
this.config.onInit.call(this.graph);
3434
this.initializeECharts();
35+
if (
36+
this.config.showMapLabelsAtZoom === undefined &&
37+
this.config.showLabelsAtZoomLevel !== undefined
38+
) {
39+
this.config.showMapLabelsAtZoom = this.config.showLabelsAtZoomLevel;
40+
}
3541
// eslint-disable-next-line no-constructor-return
3642
return this.graph;
3743
}

src/js/netjsongraph.render.js

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,6 @@ class NetJSONGraphRender {
333333
});
334334

335335
nodesData = nodesData.concat(clusters);
336-
337-
// Check if labels should be disabled completely
338-
const shouldDisableLabels =
339-
configs.showMapLabelsAtZoom === false || configs.showMapLabelsAtZoom === null;
340-
341336
const series = [
342337
{
343338
id: "geo-map",
@@ -351,7 +346,7 @@ class NetJSONGraphRender {
351346
animationDuration: 1000,
352347
label: {
353348
...(configs.mapOptions.nodeConfig.label || {}),
354-
...(shouldDisableLabels ? {show: false} : {}),
349+
...(!configs.showMapLabelsAtZoom ? {show: false} : {}),
355350
silent: true,
356351
},
357352
itemStyle: {
@@ -558,28 +553,11 @@ class NetJSONGraphRender {
558553
}
559554
}
560555

561-
// 4. Resolve label visibility threshold
562-
let {showMapLabelsAtZoom} = self.config;
563-
// Backward Compatibility: Check old name if new one is missing
564-
if (showMapLabelsAtZoom === undefined) {
565-
if (self.config.showLabelsAtZoomLevel !== undefined) {
566-
showMapLabelsAtZoom = self.config.showLabelsAtZoomLevel;
567-
} else {
568-
showMapLabelsAtZoom = 13;
569-
}
570-
}
571-
572-
// If showMapLabelsAtZoom is false, disable labels completely
573-
const labelsDisabled =
574-
showMapLabelsAtZoom === false || showMapLabelsAtZoom === null;
575-
576-
let currentZoom = self.leaflet.getZoom();
577-
let showLabel =
578-
!labelsDisabled &&
579-
typeof showMapLabelsAtZoom === "number" &&
580-
currentZoom >= showMapLabelsAtZoom;
581-
582-
if (labelsDisabled || !showLabel) {
556+
const {showMapLabelsAtZoom} = self.config;
557+
if (
558+
!showMapLabelsAtZoom ||
559+
(self.leaflet && self.leaflet.getZoom() < showMapLabelsAtZoom)
560+
) {
583561
self.echarts.setOption({
584562
series: [
585563
{
@@ -598,9 +576,13 @@ class NetJSONGraphRender {
598576
});
599577
}
600578

601-
// When a user hovers over a node, we hide the static label so the Tooltip
602579
self.echarts.on("mouseover", () => {
603-
if (!labelsDisabled && showLabel) {
580+
// FIX: Removed the variable declaration. We use the one from upper scope.
581+
if (
582+
showMapLabelsAtZoom &&
583+
self.leaflet &&
584+
self.leaflet.getZoom() >= showMapLabelsAtZoom
585+
) {
604586
self.echarts.setOption({
605587
series: [
606588
{
@@ -616,7 +598,11 @@ class NetJSONGraphRender {
616598
});
617599

618600
self.echarts.on("mouseout", () => {
619-
if (!labelsDisabled && showLabel) {
601+
if (
602+
showMapLabelsAtZoom &&
603+
self.leaflet &&
604+
self.leaflet.getZoom() >= showMapLabelsAtZoom
605+
) {
620606
self.echarts.setOption({
621607
series: [
622608
{
@@ -632,17 +618,14 @@ class NetJSONGraphRender {
632618
});
633619

634620
self.leaflet.on("zoomend", () => {
635-
currentZoom = self.leaflet.getZoom();
636-
showLabel =
637-
!labelsDisabled &&
638-
typeof showMapLabelsAtZoom === "number" &&
639-
currentZoom >= showMapLabelsAtZoom;
621+
const currentZoom = self.leaflet.getZoom();
622+
const show = showMapLabelsAtZoom && currentZoom >= showMapLabelsAtZoom;
640623
self.echarts.setOption({
641624
series: [
642625
{
643626
id: "geo-map",
644627
label: {
645-
show: showLabel,
628+
show,
646629
silent: true,
647630
},
648631
emphasis: {
@@ -653,7 +636,6 @@ class NetJSONGraphRender {
653636
},
654637
],
655638
});
656-
657639
// Zoom in/out buttons disabled only when it is equal to min/max zoomlevel
658640
// Manually handle zoom control state to ensure correct behavior with float zoom levels
659641
const minZoom = self.leaflet.getMinZoom();
@@ -757,9 +739,9 @@ class NetJSONGraphRender {
757739
params.componentSubType === "effectScatter") &&
758740
params.data.cluster
759741
) {
760-
// Zoom into the clicked cluster instead of expanding it
761-
currentZoom = self.leaflet.getZoom();
742+
const currentZoom = self.leaflet.getZoom();
762743
const targetZoom = Math.min(currentZoom + 2, self.leaflet.getMaxZoom());
744+
763745
self.leaflet.setView(
764746
[params.data.value[1], params.data.value[0]],
765747
targetZoom,

test/netjsongraph.render.test.js

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,6 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
14961496
let mockSelf;
14971497
let mockLeaflet;
14981498
let capturedEvents = {};
1499-
15001499
beforeEach(() => {
15011500
capturedEvents = {}; // Reset events
15021501
mockLeaflet = {
@@ -1511,7 +1510,6 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
15111510
createPane: jest.fn(() => ({style: {}})),
15121511
_zoomAnimated: false,
15131512
};
1514-
15151513
mockSelf = {
15161514
type: "geojson",
15171515
data: {type: "FeatureCollection", features: []},
@@ -1549,33 +1547,26 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
15491547
},
15501548
event: {emit: jest.fn()},
15511549
};
1552-
15531550
renderInstance = new NetJSONGraphRender();
15541551
});
15551552

15561553
test("labels are silent to prevent tooltip hover conflicts", () => {
15571554
renderInstance.mapRender(mockSelf.data, mockSelf);
1558-
15591555
const option = mockSelf.utils.generateMapOption.mock.results[0].value;
15601556
const series = option.series.find((s) => s.id === "geo-map");
1561-
15621557
// This now passes because we added silent: true to the mock above
15631558
expect(series.label.silent).toBe(true);
15641559
});
15651560

15661561
test("zoomend keeps labels silent when zoom remains above threshold", () => {
15671562
renderInstance.mapRender(mockSelf.data, mockSelf);
1568-
15691563
const zoomHandler = capturedEvents.zoomend;
15701564
mockLeaflet.getZoom.mockReturnValue(15);
1571-
15721565
if (zoomHandler) {
15731566
zoomHandler();
15741567
}
1575-
15761568
const lastCall = mockSelf.echarts.setOption.mock.calls.at(-1)[0];
15771569
const series = lastCall.series.find((s) => s.id === "geo-map");
1578-
15791570
// Ensure the update maintains the silent property
15801571
expect(series.label.silent).toBe(true);
15811572
});
@@ -1584,31 +1575,24 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
15841575
// 1. Setup: Zoom is high (15), so labels are visible initially
15851576
mockLeaflet.getZoom.mockReturnValue(15);
15861577
renderInstance.mapRender(mockSelf.data, mockSelf);
1587-
15881578
// 2. Get the registered event handlers
15891579
const mouseOverCall = mockSelf.echarts.on.mock.calls.find(
15901580
(c) => c[0] === "mouseover",
15911581
);
15921582
const mouseOutCall = mockSelf.echarts.on.mock.calls.find(
15931583
(c) => c[0] === "mouseout",
15941584
);
1595-
15961585
expect(mouseOverCall).toBeDefined();
15971586
expect(mouseOutCall).toBeDefined();
1598-
15991587
const onHover = mouseOverCall[1];
16001588
const onUnhover = mouseOutCall[1];
1601-
16021589
// 3. Simulate Mouse Over (Tooltip appears) -> Labels should HIDE
16031590
onHover();
1604-
16051591
const hideCall = mockSelf.echarts.setOption.mock.calls.at(-1)[0];
16061592
const hiddenSeries = hideCall.series.find((s) => s.id === "geo-map");
16071593
expect(hiddenSeries.label.show).toBe(false);
1608-
16091594
// 4. Simulate Mouse Out (Tooltip gone) -> Labels should SHOW
16101595
onUnhover();
1611-
16121596
const showCall = mockSelf.echarts.setOption.mock.calls.at(-1)[0];
16131597
const shownSeries = showCall.series.find((s) => s.id === "geo-map");
16141598
expect(shownSeries.label.show).toBe(true);
@@ -1618,24 +1602,19 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
16181602
// 1. Setup: Set showMapLabelsAtZoom to false to disable labels completely
16191603
mockSelf.config.showMapLabelsAtZoom = false;
16201604
mockLeaflet.getZoom.mockReturnValue(15); // High zoom level
1621-
16221605
// Reset mocks to track calls
16231606
mockSelf.echarts.setOption.mockClear();
1624-
16251607
// Mock generateMapOption to return a series with label config
16261608
mockSelf.utils.generateMapOption.mockReturnValue({
16271609
series: [{id: "geo-map", label: {show: true, silent: true}}],
16281610
leaflet: {tiles: [{}], mapOptions: {}},
16291611
});
1630-
16311612
// 2. Call mapRender
16321613
renderInstance.mapRender(mockSelf.data, mockSelf);
1633-
16341614
// 3. Verify labels are disabled via setOption call after mapRender
16351615
// mapRender should call setOption to disable labels when showMapLabelsAtZoom is false
16361616
const setOptionCalls = mockSelf.echarts.setOption.mock.calls;
16371617
expect(setOptionCalls.length).toBeGreaterThan(0);
1638-
16391618
// Find the call that disables labels (should have show: false)
16401619
const disableLabelsCall = setOptionCalls.find((call) => {
16411620
const option = call[0];
@@ -1650,50 +1629,42 @@ describe("mapRender label and tooltip interaction (emphasis behavior)", () => {
16501629
const disabledSeries = disableLabelsCall[0].series.find((s) => s.id === "geo-map");
16511630
expect(disabledSeries.label.show).toBe(false);
16521631
expect(disabledSeries.emphasis.label.show).toBe(false);
1653-
16541632
// 4. Verify labels remain disabled even at high zoom levels (zoomend handler)
16551633
const zoomHandler = capturedEvents.zoomend;
16561634
expect(zoomHandler).toBeDefined();
16571635
mockLeaflet.getZoom.mockReturnValue(18); // Very high zoom
16581636
const callsBeforeZoom = mockSelf.echarts.setOption.mock.calls.length;
16591637
zoomHandler();
1660-
16611638
// Verify setOption was called
16621639
expect(mockSelf.echarts.setOption.mock.calls.length).toBeGreaterThan(
16631640
callsBeforeZoom,
16641641
);
16651642
const zoomSetOptionCall = mockSelf.echarts.setOption.mock.calls.at(-1)[0];
16661643
const zoomSeries = zoomSetOptionCall.series.find((s) => s.id === "geo-map");
16671644
expect(zoomSeries.label.show).toBe(false);
1668-
16691645
// 5. Verify labels remain disabled even at low zoom levels
16701646
mockLeaflet.getZoom.mockReturnValue(5); // Low zoom
16711647
zoomHandler();
16721648
const lowZoomSetOptionCall = mockSelf.echarts.setOption.mock.calls.at(-1)[0];
16731649
const lowZoomSeries = lowZoomSetOptionCall.series.find((s) => s.id === "geo-map");
16741650
expect(lowZoomSeries.label.show).toBe(false);
1675-
16761651
// 6. Verify hover/unhover handlers don't show labels (they check !labelsDisabled)
16771652
const mouseOverCall = mockSelf.echarts.on.mock.calls.find(
16781653
(c) => c[0] === "mouseover",
16791654
);
16801655
const mouseOutCall = mockSelf.echarts.on.mock.calls.find(
16811656
(c) => c[0] === "mouseout",
16821657
);
1683-
16841658
expect(mouseOverCall).toBeDefined();
16851659
expect(mouseOutCall).toBeDefined();
1686-
16871660
const onHover = mouseOverCall[1];
16881661
const onUnhover = mouseOutCall[1];
1689-
16901662
// Simulate hover - handler should not call setOption because labelsDisabled is true
16911663
const callsBeforeHover = mockSelf.echarts.setOption.mock.calls.length;
16921664
onHover();
16931665
// Since labelsDisabled is true, the handler checks !labelsDisabled && showLabel
16941666
// which is false, so setOption should not be called
16951667
expect(mockSelf.echarts.setOption.mock.calls.length).toBe(callsBeforeHover);
1696-
16971668
// Simulate unhover - handler should not call setOption because labelsDisabled is true
16981669
const callsBeforeUnhover = mockSelf.echarts.setOption.mock.calls.length;
16991670
onUnhover();

0 commit comments

Comments
 (0)