Skip to content

Commit

Permalink
chart-axis-alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
Kinatzo committed Sep 30, 2024
1 parent 3cb587f commit cabe49f
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 75 deletions.
126 changes: 101 additions & 25 deletions packages/abstract-chart/src/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,54 @@ export function renderChart(chart: Chart): AI.AbstractImage {
const renderedBackground = generateBackground(xMin, xMax, yMin, yMax, chart);

const xNumTicks = gridWidth / chart.xPixelsPerTick;
const renderedXAxisBottom = generateXAxises("bottom", xNumTicks, xAxisesBottom, xMin, xMax, yMin, yMax, chart);
const renderedXAxisTop = generateXAxises("top", xNumTicks, xAxisesTop, xMin, xMax, yMin, yMax, chart);
const [xleft, xRight] = [
yAxisesLeft[0]?.thickness ?? chart.xGrid.thickness / 2,
yAxisesRight[0]?.thickness ?? chart.xGrid.thickness / 2,
];
const [xAxisBottom, yAxisGridBottom] = xAxises(
"bottom",
xNumTicks,
xAxisesBottom,
xMin,
xMax,
yMin,
yMax,
xleft,
xRight,
chart
);
const [xAxisTop, yAxisGridTop] = xAxises("top", xNumTicks, xAxisesTop, xMin, xMax, yMin, yMax, xleft, xRight, chart);

const yNumTicks = gridHeight / chart.yPixelsPerTick;
const renderedYAxisLeft = generateYAxises("left", yNumTicks, yAxisesLeft, xMin, xMax, yMin, yMax, chart);
const renderedYAxisRight = generateYAxises("right", yNumTicks, yAxisesRight, xMin, xMax, yMin, yMax, chart);
const [yBottom, yTop] = [
xAxisesBottom[0]?.thickness ?? chart.yGrid.thickness / 2,
xAxisesTop[0]?.thickness ?? chart.yGrid.thickness / 2,
];

const [yAxisLeft, xAxisGridLeft] = yAxises(
"left",
yNumTicks,
yAxisesLeft,
xMin,
xMax,
yMin,
yMax,
yBottom,
yTop,
chart
);
const [yAxisRight, xAxisGridRight] = yAxises(
"right",
yNumTicks,
yAxisesRight,
xMin,
xMax,
yMin,
yMax,
yBottom,
yTop,
chart
);

const renderedPoints = generatePoints(xMin, xMax, yMin, yMax, chart);
const renderedLines = generateLines(xMin, xMax, yMin, yMax, chart);
Expand Down Expand Up @@ -336,10 +378,14 @@ export function renderChart(chart: Chart): AI.AbstractImage {

const components = [
renderedBackground,
renderedXAxisBottom,
renderedXAxisTop,
renderedYAxisLeft,
renderedYAxisRight,
xAxisGridLeft,
xAxisGridRight,
yAxisGridBottom,
yAxisGridTop,
xAxisBottom,
xAxisTop,
yAxisLeft,
yAxisRight,
renderedStack,
renderedLines,
renderedPoints,
Expand All @@ -363,29 +409,39 @@ export function generateBackground(xMin: number, xMax: number, yMin: number, yMa
);
}

export function generateXAxises(
export function xAxises(
xAxis: XAxis,
xNumTicks: number,
axises: ReadonlyArray<Axis.Axis>,
xMin: number,
xMax: number,
yMin: number,
yMax: number,
xMinLineThicknessAdjustment: number,
xMaxLineThicknessAdjustment: number,
chart: Chart
): AI.Component {
): readonly [AI.Component, AI.Component] {
const components = Array<AI.Component>();
const gridLineComponents = Array<AI.Component>();
let lineY = xAxis === "bottom" ? yMin : yMax;
const dirFactor = xAxis == "bottom" ? 1 : -1;
for (const [ix, axis] of axises.entries()) {
const fullGrid = ix === 0 && xAxis === "bottom";
const xTicks = Axis.getTicks(xNumTicks, axis);
if (chart.xGrid) {
components.push(
gridLineComponents.push(
generateXAxisGridLines(xMin, xMax, lineY + dirFactor * 10, fullGrid ? yMax : lineY, xTicks, axis, chart.xGrid)
);
}
const thickness = axis.thickness ?? 1;
const lineDisp = ix == 0 ? (xAxis === "bottom" ? thickness / 2 : -thickness / 2) : 0;
components.push(
AI.createLine({ x: xMin, y: lineY }, { x: xMax, y: lineY }, axis.axisColor ?? AI.gray, axis.thickness ?? 1),
AI.createLine(
{ x: xMin - (ix == 0 ? xMinLineThicknessAdjustment : chart.xGrid.thickness / 2), y: lineY + lineDisp },
{ x: xMax + (ix == 0 ? xMaxLineThicknessAdjustment : chart.xGrid.thickness / 2), y: lineY + lineDisp },
axis.axisColor ?? AI.gray,
thickness
),
generateXAxisLabels(xMin, xMax, lineY + dirFactor * 12, xAxis === "bottom" ? "down" : "up", xTicks, axis, chart)
);

Expand Down Expand Up @@ -415,32 +471,51 @@ export function generateXAxises(
lineY += dirFactor * chart.axisWidth;
}

return AI.createGroup(xAxis + "XAxis", components);
return [AI.createGroup(xAxis + "XAxis", components), AI.createGroup(xAxis + "XAxisGridLines", gridLineComponents)];
}

export function generateYAxises(
export function yAxises(
yAxis: YAxis,
yNumTicks: number,
axises: ReadonlyArray<Axis.Axis>,
xMin: number,
xMax: number,
yMin: number,
yMax: number,
yMinLineThicknessAdjustment: number,
yMaxLineThicknessAdjustment: number,
chart: Chart
): AI.Component {
): readonly [AI.Component, AI.Component] {
const components = Array<AI.Component>();
const gridLineComponents = Array<AI.Component>();
let lineX = yAxis === "left" ? xMin : xMax;
const dirFactor = yAxis == "left" ? -1 : 1;
for (const [ix, axis] of axises.entries()) {
const fullGrid = ix === 0 && yAxis === "left";
const yTicks = Axis.getTicks(yNumTicks, axis);
if (chart.yGrid) {
components.push(
generateYAxisLines(lineX + dirFactor * 10, fullGrid ? xMax : lineX, yMin, yMax, yTicks, axis, chart.yGrid)
gridLineComponents.push(
generateYAxisLines(
lineX + dirFactor * 10,
fullGrid ? xMax : lineX,
yMin,
yMax,
yTicks,
axis,
chart.yGrid,
chart.xGrid
)
);
}
const thickness = axis.thickness ?? 1;
const lineDisp = ix == 0 ? (yAxis === "left" ? -thickness / 2 : thickness / 2) : 0;
components.push(
AI.createLine({ x: lineX, y: yMin }, { x: lineX, y: yMax }, axis.axisColor ?? AI.gray, axis.thickness ?? 1),
AI.createLine(
{ x: lineX + lineDisp, y: yMin + (ix == 0 ? yMinLineThicknessAdjustment : chart.yGrid.thickness / 2) },
{ x: lineX + lineDisp, y: yMax - (ix == 0 ? yMaxLineThicknessAdjustment : chart.yGrid.thickness / 2) },
axis.axisColor ?? AI.gray,
axis.thickness ?? 1
),
generateYAxisLabels(lineX + dirFactor * 12, yMin, yMax, yAxis, yTicks, axis, chart)
);

Expand All @@ -466,7 +541,7 @@ export function generateYAxises(
lineX += dirFactor * chart.axisWidth;
}

return AI.createGroup("YAxisLeft", components);
return [AI.createGroup("YAxisLeft", components), AI.createGroup("YAxisLeftGridLines", gridLineComponents)];
}

export function generateDataAxisesX(
Expand Down Expand Up @@ -960,13 +1035,13 @@ export function generateXAxisGridLines(
yMax: number,
xTicks: ReadonlyArray<Axis.DiscreteAxisPoint>,
xAxis: Axis.Axis,
grid: { readonly color: AI.Color; readonly thickness: number }
xGrid: { readonly color: AI.Color; readonly thickness: number }
): AI.Component {
const xLines = xTicks.map((l) => {
const x = Axis.transformValue(l.value, xMin, xMax, xAxis);
const start = AI.createPoint(x, yMin);
const end = AI.createPoint(x, yMax);
return AI.createLine(start, end, grid.color, grid.thickness);
return AI.createLine(start, end, xGrid.color, xGrid.thickness);
});

return AI.createGroup("Lines", xLines);
Expand Down Expand Up @@ -1048,13 +1123,14 @@ export function generateYAxisLines(
yMax: number,
yTicks: ReadonlyArray<Axis.DiscreteAxisPoint>,
yAxis: Axis.Axis,
grid: { readonly color: AI.Color; readonly thickness: number }
yGrid: { readonly color: AI.Color; readonly thickness: number },
xGrid: { readonly color: AI.Color; readonly thickness: number }
): AI.Component {
const yLines = yTicks.map((l) => {
const y = Axis.transformValue(l.value, yMin, yMax, yAxis);
const start = AI.createPoint(xMin, y);
const end = AI.createPoint(xMax, y);
return AI.createLine(start, end, grid.color, grid.thickness);
const start = AI.createPoint(xMin - xGrid.thickness / 2, y);
const end = AI.createPoint(xMax + xGrid.thickness / 2, y);
return AI.createLine(start, end, yGrid.color, yGrid.thickness);
});
return AI.createGroup("Lines", yLines);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function generateLineChart(hovered: string): AC.Chart {
undefined,
undefined,
undefined,
undefined,
2,
undefined,
"x-bottom-1"
),
Expand All @@ -110,58 +110,18 @@ function generateLineChart(hovered: string): AC.Chart {
undefined,
undefined,
undefined,
undefined,
2,
undefined,
"x-bottom-2"
),
],
xAxisesTop: [
AC.createLinearAxis(
xMin,
xMax,
"Days with cold top 1",
undefined,
undefined,
undefined,
undefined,
undefined,
"x-top-1"
),
AC.createLinearAxis(
xMin,
xMax,
"Days with cold top 2",
undefined,
undefined,
undefined,
undefined,
undefined,
"x-top-2"
),
AC.createLinearAxis(xMin, xMax, "Days with cold top 1", undefined, undefined, undefined, 2, undefined, "x-top-1"),
AC.createLinearAxis(xMin, xMax, "Days with cold top 2", undefined, undefined, undefined, 2, undefined, "x-top-2"),
],
yAxisesLeft: [
AC.createLinearAxis(
yMin,
yMax + 1,
"Badness left 1",
undefined,
undefined,
undefined,
undefined,
undefined,
"y-left-1"
),
AC.createLinearAxis(
yMin,
yMax + 1,
"Badness left 2",
undefined,
undefined,
undefined,
undefined,
undefined,
"y-left-2"
),
AC.createLinearAxis(yMin, yMax + 1, "Badness left 1", undefined, undefined, undefined, 2, undefined, "y-left-1"),
AC.createLinearAxis(yMin, yMax + 1, "Badness left 2", undefined, undefined, undefined, 2, undefined, "y-left-2"),
],
yAxisesRight: [
AC.createLinearAxis(
Expand All @@ -171,7 +131,7 @@ function generateLineChart(hovered: string): AC.Chart {
undefined,
undefined,
undefined,
undefined,
2,
undefined,
"y-right-1"
),
Expand All @@ -182,7 +142,7 @@ function generateLineChart(hovered: string): AC.Chart {
undefined,
undefined,
undefined,
undefined,
2,
undefined,
"y-right-2"
),
Expand Down Expand Up @@ -235,7 +195,7 @@ function generateStackedChart(): AC.Chart {
yAxis: "left",
config: [
AC.createChartStackConfig({
color: AI.red,
color: { r: 255, b: 0, g: 0, a: 120 },
label: "How bad you feel",
}),
AC.createChartStackConfig({
Expand Down Expand Up @@ -369,6 +329,8 @@ function generateLineChartDiscreteXAxis(): AC.Chart {
labelRotation: -25,
tickLabelDisp: 25,
axisFontSize: 18,
thickness: 3,
axisColor: { r: 0, b: 0, g: 0, a: 255 },
};
const yAxis: AC.Axis = {
type: "linear",
Expand All @@ -377,9 +339,11 @@ function generateLineChartDiscreteXAxis(): AC.Chart {
label: "Badness",
axisFontSize: 15,
tickFontSize: 14,
thickness: 7,
axisColor: { r: 0, b: 0, g: 0, a: 255 },
};
const chart = AC.createChart({
chartLines: series,
chartLines: [],
xAxisesBottom: [xAxis],
fontSize: 12,
yAxisesLeft: [yAxis],
Expand Down

0 comments on commit cabe49f

Please sign in to comment.