|
10 | 10 | // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ |
11 | 11 | // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ |
12 | 12 |
|
13 | | -import type { Context2D } from "../canvas-types"; |
| 13 | +import type { Canvas2D, Context2D } from "../canvas-types"; |
| 14 | +import type { PlotRect } from "../../layout/plot-layout"; |
| 15 | +import { PlotLayout } from "../../layout/plot-layout"; |
| 16 | +import type { GradientStop } from "../../theme/gradient"; |
| 17 | +import type { Vec3 } from "../../theme/palette"; |
| 18 | +import type { Theme } from "../../theme/theme"; |
| 19 | +import { |
| 20 | + renderCategoricalLegend, |
| 21 | + renderCategoricalLegendAt, |
| 22 | + renderLegend, |
| 23 | +} from "../../axis/legend"; |
14 | 24 | import type { TreeChartBase } from "./tree-chart"; |
15 | 25 | import { drawTooltipBox } from "./draw-tooltip-box"; |
16 | 26 |
|
@@ -121,3 +131,78 @@ export function renderTreeTooltip( |
121 | 131 | fontFamily, |
122 | 132 | ); |
123 | 133 | } |
| 134 | + |
| 135 | +/** |
| 136 | + * Paint a color legend (categorical swatches or numeric gradient bar) |
| 137 | + * for a tree chart. Shared by sunburst + treemap; both consult |
| 138 | + * `_colorMode` / `_uniqueColorLabels.size` / `_colorMin..max` the same |
| 139 | + * way. |
| 140 | + * |
| 141 | + * `categoricalRect`, when non-null, is used as the explicit rect for |
| 142 | + * the categorical-swatch variant (sunburst's faceted mode passes |
| 143 | + * `FacetGrid.legendRect` here). Numeric mode always derives from a |
| 144 | + * synthetic single-plot `PlotLayout` to match the legacy per-chart |
| 145 | + * branch — its gradient bar's vertical span doesn't fit the |
| 146 | + * categorical legend's compact rect. |
| 147 | + * |
| 148 | + * Returns silently when the color slot is empty, when categorical mode |
| 149 | + * has only one label, or when numeric mode has a degenerate |
| 150 | + * (`min >= max`) extent. |
| 151 | + */ |
| 152 | +export function renderTreeColorLegend( |
| 153 | + chart: TreeChartBase, |
| 154 | + canvas: Canvas2D, |
| 155 | + palette: Vec3[], |
| 156 | + stops: GradientStop[], |
| 157 | + theme: Theme, |
| 158 | + cssWidth: number, |
| 159 | + cssHeight: number, |
| 160 | + categoricalRect: PlotRect | null = null, |
| 161 | +): void { |
| 162 | + if (chart._colorMode === "series" && chart._uniqueColorLabels.size > 1) { |
| 163 | + if (categoricalRect) { |
| 164 | + renderCategoricalLegendAt( |
| 165 | + canvas, |
| 166 | + categoricalRect, |
| 167 | + chart._uniqueColorLabels, |
| 168 | + palette, |
| 169 | + theme, |
| 170 | + ); |
| 171 | + } else { |
| 172 | + renderCategoricalLegend( |
| 173 | + canvas, |
| 174 | + syntheticLegendLayout(cssWidth, cssHeight), |
| 175 | + chart._uniqueColorLabels, |
| 176 | + palette, |
| 177 | + theme, |
| 178 | + ); |
| 179 | + } |
| 180 | + } else if ( |
| 181 | + chart._colorMode === "numeric" && |
| 182 | + chart._colorMin < chart._colorMax |
| 183 | + ) { |
| 184 | + renderLegend( |
| 185 | + canvas, |
| 186 | + syntheticLegendLayout(cssWidth, cssHeight), |
| 187 | + { |
| 188 | + min: chart._colorMin, |
| 189 | + max: chart._colorMax, |
| 190 | + label: chart._colorName, |
| 191 | + }, |
| 192 | + stops, |
| 193 | + theme, |
| 194 | + chart.getColumnFormatter(chart._colorName, "value"), |
| 195 | + ); |
| 196 | + } |
| 197 | +} |
| 198 | + |
| 199 | +function syntheticLegendLayout( |
| 200 | + cssWidth: number, |
| 201 | + cssHeight: number, |
| 202 | +): PlotLayout { |
| 203 | + return new PlotLayout(cssWidth, cssHeight, { |
| 204 | + hasXLabel: false, |
| 205 | + hasYLabel: false, |
| 206 | + hasLegend: true, |
| 207 | + }); |
| 208 | +} |
0 commit comments