Skip to content

Commit

Permalink
fixup! ui-trackoccupancydiagram: highlight selected train
Browse files Browse the repository at this point in the history
Signed-off-by: Yohh <[email protected]>
  • Loading branch information
Yohh committed Dec 17, 2024
1 parent 5de4cbf commit 7bbc676
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import {
CANVAS_PADDING,
OCCUPANCY_ZONE_START,
OCCUPANCY_ZONE_HEIGHT,
FONTS,
COLORS,
} from '../../consts';
import type { OccupancyZone, Track } from '../../types';

const { SANS } = FONTS;
const { REMAINING_TRAINS_BACKGROUND, WHITE_100, SELECTION_20 } = COLORS;
const REMAINING_TRAINS_WIDTH = 70;
const REMAINING_TRAINS_HEIGHT = 24;
Expand All @@ -17,6 +19,7 @@ const MAX_ZONES = 9;
const X_BACKGROUND_OFFSET = 22;
const X_TROUGHTRAIN_PADDING = 4;
const Y_BACKGROUND_OFFSET = 20;
const SELECTED_TRAIN_ID_GRADIANT = 2;

type DrawZone = {
ctx: CanvasRenderingContext2D;
Expand Down Expand Up @@ -67,7 +70,7 @@ const drawRemainingTrainsBox = ({ ctx, text, textX, textY }: DrawRemainingTrains
ctx.fill();
ctx.stroke();
ctx.fillStyle = WHITE_100;
ctx.font = '400 12px IBM Plex Sans';
ctx.font = SANS;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text, textX + REMAINING_TRAINS_WIDTH / 2, textY + REMAINING_TRAINS_HEIGHT / 2);
Expand Down Expand Up @@ -149,9 +152,24 @@ export const drawOccupancyZones = ({
// draw at least 9 zones and zones texts
// if there are more than 9 zones, draw a box with the remaining trains
if (counter <= MAX_ZONES) {
if (selectedTrainId === zone.id) {
ctx.fillStyle = SELECTION_20;
ctx.beginPath();
ctx.roundRect(
arrivalTime - X_BACKGROUND_OFFSET - (isThroughTrain ? X_TROUGHTRAIN_PADDING : 0),
yPosition - Y_BACKGROUND_OFFSET,
departureTime -
arrivalTime +
X_BACKGROUND_OFFSET * 2 +
(isThroughTrain ? X_TROUGHTRAIN_PADDING * 2 : 0),
Y_BACKGROUND_OFFSET * 2,
SELECTED_TRAIN_ID_GRADIANT
);
ctx.fill();
}

ctx.fillStyle = zone.color;
ctx.strokeStyle = WHITE_100;
ctx.lineWidth = 1;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';

Expand All @@ -161,61 +179,26 @@ export const drawOccupancyZones = ({
drawDefaultZone({ ctx, arrivalTime, departureTime, yPosition });
}

if (departureTime >= lastDepartureTimePixel) lastDepartureTimePixel = departureTime;

// draw at least 9 zones and zones texts
// if there are more than 9 zones, draw a box with the remaining trains
if (counter <= MAX_ZONES) {
// draw a yellow rect with a height of 64px, that begins 22px before arrival time
if (selectedTrainId === zone.id) {
ctx.fillStyle = SELECTION_20;
ctx.beginPath();
ctx.roundRect(
arrivalTime - X_BACKGROUND_OFFSET - (isThroughTrain ? X_TROUGHTRAIN_PADDING : 0),
yPosition - Y_BACKGROUND_OFFSET,
departureTime -
arrivalTime +
X_BACKGROUND_OFFSET * 2 +
(isThroughTrain ? X_TROUGHTRAIN_PADDING * 2 : 0),
Y_BACKGROUND_OFFSET * 2,
2
);
ctx.fill();
}

ctx.fillStyle = zone.color;
ctx.strokeStyle = WHITE_100;
ctx.lineWidth = 1;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';

if (isThroughTrain) {
drawThroughTrain({ ctx, arrivalTime });
} else {
drawDefaultZone({ ctx, arrivalTime, departureTime, yPosition });
}

drawOccupancyZonesTexts({
ctx,
zone,
arrivalTime,
departureTime,
yPosition,
isThroughTrain,
selectedTrainId,
});
} else if (counter === MAX_ZONES + 1) {
const textX =
primaryArrivalTimePixel +
(lastDepartureTimePixel - primaryArrivalTimePixel) / 2 -
REMAINING_TRAINS_WIDTH / 2;
const textY = OCCUPANCY_ZONE_START - REMAINING_TEXT_OFFSET;
const text = `+${sortedOccupancyZone.length - sortedIndex} trains`;

drawRemainingTrainsBox({ ctx, text, textX, textY });

break;
}
drawOccupancyZonesTexts({
ctx,
zone,
arrivalTime,
departureTime,
yPosition,
isThroughTrain,
selectedTrainId,
});
} else if (counter === MAX_ZONES + 1) {
const textX =
primaryArrivalTimePixel +
(lastDepartureTimePixel - primaryArrivalTimePixel) / 2 -
REMAINING_TRAINS_WIDTH / 2;
const textY = OCCUPANCY_ZONE_START - REMAINING_TEXT_OFFSET;
const text = `+${sortedOccupancyZone.length - sortedIndex} trains`;

drawRemainingTrainsBox({ ctx, text, textX, textY });

break;
}
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
OCCUPANCY_ZONE_START,
MINUTES_TEXT_OFFSET,
STATION_TEXT_OFFSET,
FONTS,
COLORS,
} from '../../consts';
import { MINUTES_TEXT_OFFSET, STATION_TEXT_OFFSET, FONTS, COLORS } from '../../consts';
import { drawText } from '../../utils';

const BREAKPOINTS = {
Expand All @@ -18,8 +12,11 @@ const X_MEDIUM_POSITION_OFFSET_BACKGROUND = 20;
const Y_INITIAL_POSITION_OFFSET = 5;
const Y_INITIAL_POSITION_OFFSET_BACKGROUND = 18;
const X_TROUGHTRAIN_PADDING = 2;
const X_SELECTED_TROUGHTRAIN_PADDING = 8;
const X_THROUGHTRAIN_OFFSET = 4;
const Y_MEDIUM_POSITION_OFFSET_BACKGROUND = 32;
const Y_MEDIUM_POSITION_OFFSET = 14;
const ROTATE_VALUE = (-30 * Math.PI) / 180;

const { SANS, MONO } = FONTS;
const { WHITE_100, GREY_50, GREY_60, GREY_80, SELECTION_20 } = COLORS;
Expand Down Expand Up @@ -53,24 +50,26 @@ export const drawOccupancyZonesTexts = ({
const isBelowBreakpoint = (breakpoint: keyof typeof BREAKPOINTS) =>
zoneOccupancyLength < BREAKPOINTS[breakpoint];

const textLength = ctx.measureText(zone.originStation!).width;
const originTextLength = ctx.measureText(zone.originStation!).width;
const nameTextLength = ctx.measureText(zone.arrivalTrainName).width;

const { xOriginName, yOriginName } = {
xOriginName: isBelowBreakpoint('medium')
? arrivalTime - textLength + STROKE_WIDTH
? arrivalTime - originTextLength + STROKE_WIDTH
: arrivalTime + X_INITIAL_POSITION_OFFSET,
yOriginName: isBelowBreakpoint('medium')
? yPosition - Y_MEDIUM_POSITION_OFFSET
: yPosition - Y_INITIAL_POSITION_OFFSET,
};

const xTrainName = isBelowBreakpoint('medium')
? arrivalTime - X_MEDIUM_POSITION_OFFSET_BACKGROUND
: arrivalTime;
const yTrainName = isBelowBreakpoint('medium')
? yPosition - Y_MEDIUM_POSITION_OFFSET_BACKGROUND
: yPosition - Y_INITIAL_POSITION_OFFSET_BACKGROUND;
const { xTrainName, yTrainName } = {
xTrainName: isBelowBreakpoint('medium')
? arrivalTime - X_MEDIUM_POSITION_OFFSET_BACKGROUND
: arrivalTime,
yTrainName: isBelowBreakpoint('medium')
? yPosition - Y_MEDIUM_POSITION_OFFSET_BACKGROUND
: yPosition - Y_INITIAL_POSITION_OFFSET_BACKGROUND,
};

const xArrivalPosition = isBelowBreakpoint('small') ? 'right' : 'center';
const xDeparturePosition = isBelowBreakpoint('small') ? 'left' : 'center';
Expand All @@ -80,19 +79,20 @@ export const drawOccupancyZonesTexts = ({
width: STROKE_WIDTH,
};

// for setup canvas main font, we have to import directly in the file the font generated by the font-face
ctx.font = '400 12px IBM Plex Mono';

// train name
if (selectedTrainId === zone.id) {
ctx.save();
ctx.translate(xTrainName, yTrainName);
ctx.rotate((-30 * Math.PI) / 180);
ctx.rotate(ROTATE_VALUE);
ctx.fillStyle = SELECTION_20;
ctx.beginPath();
ctx.roundRect(
-X_BACKGROUND_PADDING -
(isThroughTrain ? X_TROUGHTRAIN_PADDING : 0) -
(isBelowBreakpoint('medium') ? 8 : 0),
(isBelowBreakpoint('medium') ? X_SELECTED_TROUGHTRAIN_PADDING : 0),
0,
nameTextLength + X_BACKGROUND_PADDING * 2,
Y_INITIAL_POSITION_OFFSET_BACKGROUND
Expand All @@ -104,10 +104,10 @@ export const drawOccupancyZonesTexts = ({
drawText({
ctx,
text: zone.arrivalTrainName,
x: isThroughTrain ? xOriginName - 4 : xOriginName,
x: isThroughTrain ? xOriginName - X_THROUGHTRAIN_OFFSET : xOriginName,
y: yOriginName,
color: GREY_50,
rotateAngle: -30,
rotateAngle: ROTATE_VALUE,
stroke: {
color: WHITE_100,
width: STROKE_WIDTH,
Expand All @@ -118,7 +118,7 @@ export const drawOccupancyZonesTexts = ({
drawText({
ctx,
text: zone.arrivalTime.getMinutes().toLocaleString('fr-FR', { minimumIntegerDigits: 2 }),
x: isThroughTrain ? arrivalTime - 4 : arrivalTime,
x: isThroughTrain ? arrivalTime - X_THROUGHTRAIN_OFFSET : arrivalTime,
y: yPosition + MINUTES_TEXT_OFFSET,
color: GREY_80,
xPosition: xArrivalPosition,
Expand All @@ -136,15 +136,15 @@ export const drawOccupancyZonesTexts = ({
color: GREY_80,
xPosition: xDeparturePosition,
yPosition: 'top',
font: '400 12px IBM Plex Sans',
font: SANS,
stroke: textStroke,
});

// origin & destination
drawText({
ctx,
text: zone.originStation!,
x: isThroughTrain ? arrivalTime - 4 : arrivalTime,
x: isThroughTrain ? arrivalTime - X_THROUGHTRAIN_OFFSET : arrivalTime,
y: yPosition - STATION_TEXT_OFFSET,
color: GREY_60,
xPosition: 'right',
Expand All @@ -156,7 +156,7 @@ export const drawOccupancyZonesTexts = ({
drawText({
ctx,
text: zone.destinationStation!,
x: isThroughTrain ? departureTime + 4 : departureTime,
x: isThroughTrain ? departureTime + X_THROUGHTRAIN_OFFSET : departureTime,
y: yPosition - STATION_TEXT_OFFSET,
color: GREY_60,
xPosition: 'left',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const drawRails = ({
ctx: CanvasRenderingContext2D;
}) => {
ctx.clearRect(xStart, yStart, width, 9);
ctx.beginPath();

ctx.fillStyle = WHITE_50;
ctx.strokeStyle = stroke;
ctx.beginPath();
Expand Down
2 changes: 1 addition & 1 deletion ui-trackoccupancydiagram/src/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const drawText = ({
}: DrawTextType) => {
ctx.save();
ctx.translate(x, y);
ctx.rotate((rotateAngle * Math.PI) / 180);
ctx.rotate(rotateAngle);

ctx.font = font;
ctx.textAlign = xPosition;
Expand Down

0 comments on commit 7bbc676

Please sign in to comment.