Skip to content

Commit 1febd38

Browse files
committed
feat(layer): add zIndex to ChartSpec for controlling layer render order
Layers in a LayerSpec now respect an optional zIndex property that controls paint order independent of axis assignment. Default behavior is unchanged (layers render in array order, later layers paint on top). Axis assignment (left/right y) is always determined by array position, not zIndex.
1 parent b3f2bd2 commit 1febd38

2 files changed

Lines changed: 25 additions & 2 deletions

File tree

packages/core/src/types/spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,13 @@ export interface ChartSpec {
875875
* - AnimationConfig: full control via enter/update/exit phases
876876
*/
877877
animation?: AnimationSpec;
878+
/**
879+
* Render order within a LayerSpec. Higher values render on top.
880+
* When omitted, layers render in array order (later layers paint on top).
881+
* Axis assignment (left/right y) is always determined by array position,
882+
* not zIndex.
883+
*/
884+
zIndex?: number;
878885
}
879886

880887
/**

packages/engine/src/compile.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,15 @@ export function compileLayer(spec: LayerSpec, options: CompileOptions): ChartLay
500500
seenLabels.add(entry.label);
501501
}
502502

503-
for (const leaf of leaves) {
503+
// Sort leaves by zIndex for render order while preserving original indices
504+
// for axis assignment. Default zIndex is the array position.
505+
const indexedLeaves = leaves.map((leaf, i) => ({
506+
leaf,
507+
zIndex: (leaf as ChartSpec).zIndex ?? i,
508+
}));
509+
indexedLeaves.sort((a, b) => a.zIndex - b.zIndex);
510+
511+
for (const { leaf } of indexedLeaves) {
504512
const leafLayout = compileChart(leaf as unknown, options);
505513

506514
allMarks.push(...leafLayout.marks);
@@ -821,14 +829,22 @@ function compileLayerIndependent(
821829
}
822830
}
823831

832+
// Determine mark render order. By default, layer 0 paints first (behind),
833+
// layer 1 paints second (on top). zIndex on the original leaf specs can
834+
// reverse this so e.g. a line in layer 0 renders on top of bars in layer 1.
835+
const z0 = leaf0.zIndex ?? 0;
836+
const z1 = leaf1.zIndex ?? 1;
837+
const marks =
838+
z0 <= z1 ? [...adjustedMarks0, ...taggedMarks1] : [...taggedMarks1, ...adjustedMarks0];
839+
824840
return {
825841
...layout0,
826842
axes: {
827843
x: layout0.axes.x,
828844
y: layout0.axes.y,
829845
y2: y2Axis,
830846
},
831-
marks: [...adjustedMarks0, ...taggedMarks1],
847+
marks,
832848
legend: {
833849
...layout0.legend,
834850
entries: mergedLegendEntries,

0 commit comments

Comments
 (0)