Skip to content

Commit

Permalink
Fixed an issue where multiple axis were not being shown
Browse files Browse the repository at this point in the history
  • Loading branch information
cohansen committed Dec 19, 2023
1 parent 1f885d8 commit d0d5af1
Showing 1 changed file with 84 additions and 72 deletions.
156 changes: 84 additions & 72 deletions src/components/timeline/RowYAxes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
const dispatch = createEventDispatcher();
let g: SVGGElement;
let xRangeAxisDrawn: boolean;
$: if (drawHeight && g && yAxes && resourcesByViewLayerId && layers) {
draw();
Expand All @@ -33,16 +34,18 @@
let marginWidth = 0;
const axisClass = 'y-axis';
gSelection.selectAll(`.${axisClass}`).remove();
// TODO: Use this flag to only draw the xRange axis once, can be removed when the TODO below is resolved.
xRangeAxisDrawn = false;
for (let i = 0; i < yAxes.length; ++i) {
const axis = yAxes[i];
const xRangeLayers = layers.filter(layer => layer.yAxisId === axis.id && layer.chartType === 'x-range');
const axisG = gSelection.append('g').attr('class', axisClass);
axisG.selectAll('*').remove();
if (xRangeLayers.length === 1) {
if (xRangeLayers.length === 1 && !xRangeAxisDrawn) {
const layer = xRangeLayers[0] as XRangeLayer;
const resources = resourcesByViewLayerId[layer.id];
const xRangeAxisG = gSelection.append('g').attr('class', axisClass);
xRangeAxisG.selectAll('*').remove();
/**
* TODO: This is a temporary solution to showing state mode changes as a line chart.
Expand All @@ -69,88 +72,97 @@
const axisMargin = 2;
const startPosition = -(totalWidth + axisMargin * i);
marginWidth += i > 0 ? axisMargin : 0;
axisG.attr('transform', `translate(${startPosition}, 0)`);
axisG.style('color', axis.color);
axisG.call(axisLeft);
axisG.call(g => g.select('.domain').remove());
}
} else {
// Get color for axis by examining associated layers. If more than one layer is associated,
// use the default axis color, otherwise use the color from the layer.
// TODO we don't expose y-axis color and this refactor would elimate need to store it in view.
// That is unless we want to allow user override of this behavior?
let color = axis.color;
const yAxisLayers = layers.filter(layer => layer.yAxisId === axis.id && layer.chartType === 'line');
if (yAxisLayers.length === 1) {
color = (yAxisLayers[0] as LineLayer).lineColor;
}
// TODO deprecate these view properties?
// const labelColor = axis.label?.color || 'black';
// const labelFontFace = axis.label?.fontFace || 'sans-serif';
// const labelFontSize = axis.label?.fontSize || 12;
// const labelText = axis.label.text;
const tickCount = axis.tickCount || 1;
if (
tickCount > 0 &&
axis.scaleDomain &&
axis.scaleDomain.length === 2 &&
typeof axis.scaleDomain[0] === 'number' &&
typeof axis.scaleDomain[1] === 'number'
) {
const domain = axis.scaleDomain;
const scale = getYScale(domain, drawHeight);
const axisLeft = d3AxisLeft(scale)
.tickSizeInner(0)
.tickSizeOuter(0)
.ticks(tickCount)
.tickFormat(n => {
// Format -1 to 1 as normal numbers instead of <number>m (milli) which d3
// does out of the box to align with various standards but which can be
// commonly confused for M (million).
const number = n as number;
if (number > -1 && number < 1) {
return d3Format('.2r')(n);
}
return d3Format('~s')(n);
})
.tickPadding(2);
xRangeAxisG.attr('transform', `translate(${startPosition}, 0)`);
xRangeAxisG.style('color', axis.color);
xRangeAxisG.call(axisLeft);
xRangeAxisG.call(g => g.select('.domain').remove());
const axisMargin = 2;
const startPosition = -(totalWidth + axisMargin * i);
marginWidth += i > 0 ? axisMargin : 0;
axisG.attr('transform', `translate(${startPosition}, 0)`);
axisG.style('color', color);
if (domain.length === 2 && domain[0] !== null && domain[1] !== null) {
axisG.call(axisLeft);
axisG.call(g => g.select('.domain').remove());
}
totalWidth += getBoundingClientRectWidth(xRangeAxisG.node());
xRangeAxisDrawn = true;
}
}
const axisG = gSelection.append('g').attr('class', axisClass);
axisG.selectAll('*').remove();
// Draw separator
axisG
.append('line')
.attr('x1', 2)
.attr('y1', 0)
.attr('x2', 2)
.attr('y2', drawHeight)
.style('stroke', '#EBECEC')
.style('stroke-width', 2);
// Get color for axis by examining associated layers. If more than one layer is associated,
// use the default axis color, otherwise use the color from the layer.
// TODO we don't expose y-axis color and this refactor would elimate need to store it in view.
// That is unless we want to allow user override of this behavior?
let color = axis.color;
const yAxisLayers = layers.filter(layer => layer.yAxisId === axis.id && layer.chartType === 'line');
if (yAxisLayers.length === 1) {
color = (yAxisLayers[0] as LineLayer).lineColor;
}
const axisGElement: SVGGElement | null = axisG.node();
if (axisGElement !== null) {
// TODO might be able to save minor perf by getting bounding rect of entire
// container instead of each individual axis?
totalWidth += axisGElement.getBoundingClientRect().width;
// TODO deprecate these view properties?
// const labelColor = axis.label?.color || 'black';
// const labelFontFace = axis.label?.fontFace || 'sans-serif';
// const labelFontSize = axis.label?.fontSize || 12;
// const labelText = axis.label.text;
const tickCount = axis.tickCount || 1;
if (
tickCount > 0 &&
axis.scaleDomain &&
axis.scaleDomain.length === 2 &&
typeof axis.scaleDomain[0] === 'number' &&
typeof axis.scaleDomain[1] === 'number'
) {
const domain = axis.scaleDomain;
const scale = getYScale(domain, drawHeight);
const axisLeft = d3AxisLeft(scale)
.tickSizeInner(0)
.tickSizeOuter(0)
.ticks(tickCount)
.tickFormat(n => {
// Format -1 to 1 as normal numbers instead of <number>m (milli) which d3
// does out of the box to align with various standards but which can be
// commonly confused for M (million).
const number = n as number;
if (number > -1 && number < 1) {
return d3Format('.2r')(n);
}
return d3Format('~s')(n);
})
.tickPadding(2);
const axisMargin = 2;
const startPosition = -(totalWidth + axisMargin * i);
marginWidth += i > 0 ? axisMargin : 0;
axisG.attr('transform', `translate(${startPosition}, 0)`);
axisG.style('color', color);
if (domain.length === 2 && domain[0] !== null && domain[1] !== null) {
axisG.call(axisLeft);
axisG.call(g => g.select('.domain').remove());
}
}
// Draw separator
axisG
.append('line')
.attr('x1', 2)
.attr('y1', 0)
.attr('x2', 2)
.attr('y2', drawHeight)
.style('stroke', '#EBECEC')
.style('stroke-width', 2);
totalWidth += getBoundingClientRectWidth(axisG.node());
}
totalWidth += marginWidth;
// Dispatch the width so the RowHeader can recalculate the label width.
dispatch('updateYAxesWidth', totalWidth);
}
}
function getBoundingClientRectWidth(axisG: SVGGElement | null): number {
if (axisG !== null) {
return axisG.getBoundingClientRect().width + 4;
}
return 0;
}
</script>

<svg class="row-y-axes">
Expand Down

0 comments on commit d0d5af1

Please sign in to comment.