Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 112 additions & 57 deletions src/svgs/shmetro/indoor/station-shmetro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ import { useRootSelector } from '../../../redux';
*/
export type NameDirection = 'upward' | 'downward' | 'left' | 'right';

const oppositeNameDirection: Record<NameDirection, NameDirection> = {
upward: 'downward',
downward: 'upward',
left: 'right',
right: 'left',
};

interface Props {
stnId: string;
nameDirection: NameDirection;
services: Services[];
color?: ColourHex; // Control the station color if coline is in effect.
isSh2024IndoorLoop?: boolean;
}

export const StationSHMetro = (props: Props) => {
const { stnId, nameDirection, services, color } = props;
const { stnId, nameDirection, services, color, isSh2024IndoorLoop = false } = props;
const { stn_list, info_panel_type } = useRootSelector(store => store.param);
const stnInfo = stn_list[stnId];

Expand All @@ -36,11 +44,11 @@ export const StationSHMetro = (props: Props) => {
...(stnInfo.transfer.groups.at(2)?.lines || []),
].length;

stationIconColor.stroke = 'var(--rmg-theme-colour)';
stationIconColor.stroke = color ?? 'var(--rmg-theme-colour)';
if (stnInfo.services.length === 3) {
stationIconStyle = 'stn_sh_2020_direct';
stationIconStyle = 'direct_indoor_sh';
} else if (stnInfo.services.length === 2) {
stationIconStyle = 'stn_sh_2020_express';
stationIconStyle = 'express_indoor_sh';
} else if (osi_osysi_length > 1) {
// 不管多少条站内换乘,只要有超过1个的出站换乘就是3个圆了
stationIconStyle = 'stn_sh_2024_osysi3';
Expand All @@ -56,7 +64,7 @@ export const StationSHMetro = (props: Props) => {
} else {
stationIconStyle = 'stn_sh_2024';
delete stationIconColor.stroke;
stationIconColor.fill = 'var(--rmg-theme-colour)';
stationIconColor.fill = color ?? 'var(--rmg-theme-colour)';
}
} else {
const non_osysi_transfer = [
Expand All @@ -72,14 +80,22 @@ export const StationSHMetro = (props: Props) => {
non_osysi_transfer.length > 0 ? 'var(--rmg-black)' : (color ?? 'var(--rmg-theme-colour)');
}

const dr = nameDirection === 'left' || nameDirection === 'right' ? 90 : 0;
const dr =
nameDirection === 'left' || nameDirection === 'right'
? info_panel_type === PanelTypeShmetro.sh2024
? nameDirection === 'left'
? -90
: 90
: 90
: 0;
return (
<>
<StationNameGElement
name={stnInfo.localisedName}
groups={stnInfo.transfer.groups}
nameDirection={nameDirection}
services={services}
isSh2024IndoorLoop={isSh2024IndoorLoop}
/>
<use
xlinkHref={`#${stationIconStyle}`}
Expand Down Expand Up @@ -122,10 +138,11 @@ interface StationNameGElementProps {
groups: InterchangeGroup[];
nameDirection: NameDirection;
services: Services[];
isSh2024IndoorLoop?: boolean;
}

const StationNameGElement = (props: StationNameGElementProps) => {
const { name, groups, nameDirection, services } = props;
const { name, groups, nameDirection, services, isSh2024IndoorLoop = false } = props;
const { en: enName = '' } = name;
const nameENLn = enName.split('\\').length;
const { info_panel_type } = useRootSelector(store => store.param);
Expand Down Expand Up @@ -178,6 +195,7 @@ const StationNameGElement = (props: StationNameGElementProps) => {
}, [name.zh, name.en]);

const panel_type = info_panel_type as PanelTypeShmetro;
const isSh2024 = info_panel_type === PanelTypeShmetro.sh2024;
const verticalLineY = {
[PanelTypeShmetro.sh2024]: { upward: -15, downward: -30 },
[PanelTypeShmetro.sh2020]: { upward: -23, downward: -10 },
Expand All @@ -189,45 +207,84 @@ const StationNameGElement = (props: StationNameGElementProps) => {
stationNameDY(info_panel_type, nameDirection, nameENLn) -
STATION_NAME_2024_ZH_FONT_SIZE / 2 -
INT_BOX_SIZE.height / 2,
left: 7,
right: 7,
left: 12,
right: 12,
};
const dyByDir: Record<NameDirection, number> = { upward: 60, downward: -30, left: 0, right: 0 };
const effectiveIntBoxDir = isSh2024IndoorLoop ? oppositeNameDirection[nameDirection] : nameDirection;
const intBoxDYCompensation = isSh2024IndoorLoop ? dyByDir[effectiveIntBoxDir] - dy : 0;
// stn_sh_2024 icon edges: y=-18 (top) .. 6 (bottom). IntBoxGroup2024 dy = box bottom edge.
const intBoxGap = 5;
const effectiveIntBoxDY = (() => {
if (!isSh2024IndoorLoop) return intBoxGroup2024DY[nameDirection];
if (effectiveIntBoxDir === 'upward' || effectiveIntBoxDir === 'downward') {
const undoParent = -dy;
const iconEdge = effectiveIntBoxDir === 'upward' ? 6 : -18;
return effectiveIntBoxDir === 'upward'
? undoParent + iconEdge + intBoxGap + INT_BOX_SIZE.height
: undoParent + iconEdge - intBoxGap;
}
return intBoxGroup2024DY[effectiveIntBoxDir] + intBoxDYCompensation;
})();

if (isSh2024) {
return (
<g transform={`translate(0,${dy})`}>
{nameDirection === 'upward' || nameDirection === 'downward' ? (
<line
y1={verticalLineY[panel_type][nameDirection]}
y2={nameDirection === 'upward' ? -23 - 25 - 6 : 20}
stroke="black"
/>
) : (
<line x1={0} x2={nameDirection === 'left' ? -60 : 60} y1={0} y2={0} stroke="black" />
)}

{effectiveIntBoxDir === 'left' || effectiveIntBoxDir === 'right' ? (
<g
transform={`translate(${effectiveIntBoxDir === 'left' ? nameSize.x - 10 : nameSize.x + nameSize.width + 10},${intBoxDYCompensation})`}
>
<IntBoxGroup2024
groups={groups}
dy={intBoxGroup2024DY[effectiveIntBoxDir]}
align={effectiveIntBoxDir === 'left' ? 'end' : 'start'}
/>
</g>
) : (
<IntBoxGroup2024 groups={groups} dy={effectiveIntBoxDY} />
)}

<StationName ref={nameRef} stnName={name} nameDirection={nameDirection} fill="black" />
</g>
);
}

return (
<g transform={`translate(0,${dy})`}>
{nameDirection === 'upward' || nameDirection === 'downward' ? (
<>
{info_panel_type !== PanelTypeShmetro.sh2024 && (
<line
x1={-nameSize.width / 2}
x2={nameSize.width / 2}
y1={verticalLineY[panel_type][nameDirection]}
y2={verticalLineY[panel_type][nameDirection]}
stroke="black"
/>
)}
<line
x1={-nameSize.width / 2}
x2={nameSize.width / 2}
y1={verticalLineY[panel_type][nameDirection]}
y2={
// TODO: this is too ugly
nameDirection === 'upward'
? -23 - 25 - (info_panel_type === PanelTypeShmetro.sh2024 ? 6 : 0)
: 20
}
y2={verticalLineY[panel_type][nameDirection]}
stroke="black"
/>
<line
y1={verticalLineY[panel_type][nameDirection]}
y2={nameDirection === 'upward' ? -23 - 25 : 20}
stroke="black"
/>
</>
) : (
<>
{info_panel_type !== PanelTypeShmetro.sh2024 && (
<line
x1={nameDirection === 'left' ? -50 : 15}
x2={nameDirection === 'left' ? -15 : 50}
y1={0}
y2={0}
stroke="black"
/>
)}
<line
x1={nameDirection === 'left' ? -50 : 15}
x2={nameDirection === 'left' ? -15 : 50}
y1={0}
y2={0}
stroke="black"
/>
<line
x1={nameDirection === 'left' ? -50 : 50}
x2={nameDirection === 'left' ? -50 : 50}
Expand All @@ -238,21 +295,17 @@ const StationNameGElement = (props: StationNameGElementProps) => {
</>
)}

{info_panel_type !== PanelTypeShmetro.sh2024 ? (
[...(groups[0].lines || []), ...(groups[1]?.lines || [])].length && (
<IntBoxGroup
intInfos={[groups[0].lines || [], groups[1]?.lines || []]}
arrowDirection={nameDirection}
services={services}
/>
)
) : (
<IntBoxGroup2024 groups={groups} dy={intBoxGroup2024DY[nameDirection]} />
{[...(groups[0].lines || []), ...(groups[1]?.lines || [])].length && (
<IntBoxGroup
intInfos={[groups[0].lines || [], groups[1]?.lines || []]}
arrowDirection={nameDirection}
services={services}
/>
)}

<StationName ref={nameRef} stnName={name} nameDirection={nameDirection} fill="black" />

{info_panel_type !== PanelTypeShmetro.sh2024 && groups[2]?.lines?.length && (
{groups[2]?.lines?.length && (
<g transform={`translate(${osysi_dx},${osysi_dy})`}>
<OSysIText osysiInfos={groups[2].lines} nameDirection={nameDirection} />
</g>
Expand Down Expand Up @@ -447,13 +500,14 @@ const IntBoxGroup = (props: IntBoxGroupProps & SVGProps<SVGGElement>) => {
};

const IntBoxGroup2024 = forwardRef(function IntBoxGroup2024(
props: { groups: InterchangeGroup[]; dy: number },
props: { groups: InterchangeGroup[]; dy: number; align?: 'start' | 'center' | 'end' },
ref: Ref<SVGGElement>
) {
const { groups, dy } = props;
const { groups, dy, align = 'center' } = props;
const directionPolarity = 1;

const transfer = [groups.at(0)?.lines ?? [], groups.at(1)?.lines ?? [], groups.at(2)?.lines ?? []];
const outOfStationTransfer = [...transfer[1], ...transfer[2]];

const [outOfSystemLine, setOutOfSystemLine] = useState(0); // also for start point of 出站换乘
const [intBoxesDX, setIntBoxesDX] = useState<{ [k in string]: number }>({});
Expand Down Expand Up @@ -489,7 +543,7 @@ const IntBoxGroup2024 = forwardRef(function IntBoxGroup2024(
dx += getBBoxWidth(info);
});
let outOfStationLine = 0;
if (transfer[1].length) {
if (outOfStationTransfer.length) {
// there will be a line and a text element for 出站换乘
// each will take 22px
const elementWidth = INT_BOX_SIZE.height;
Expand All @@ -502,20 +556,17 @@ const IntBoxGroup2024 = forwardRef(function IntBoxGroup2024(
outOfStationLine = 0;
dx += elementWidth;
}
transfer[1].forEach(info => {
outOfStationTransfer.forEach(info => {
dx += getBBoxWidth(info);
});
}
transfer[2].forEach(info => {
dx += getBBoxWidth(info);
});
setIntBoxesDX(intBoxDX);
setOutOfSystemLine(outOfStationLine);
setIntBoxGroupWidth(dx);
}, [JSON.stringify(transfer)]);
}, [JSON.stringify(transfer), JSON.stringify(outOfStationTransfer)]);

// only in case of one non out-of-station text line transfer, the text will be centered
const nonOutOfStationTransfer = [groups.at(0)?.lines ?? [], groups.at(2)?.lines ?? []];
const nonOutOfStationTransfer = [groups.at(0)?.lines ?? []];
const onlyOneNonOutOfStationTextInt =
transfer.flat().length === 1 &&
nonOutOfStationTransfer.flat().length === 1 &&
Expand All @@ -541,11 +592,16 @@ const IntBoxGroup2024 = forwardRef(function IntBoxGroup2024(
);
};

const dx = onlyOneNonOutOfStationTextInt ? 0 : -intBoxGroupWidth / 2;
const dx = (() => {
if (align === 'end') return -intBoxGroupWidth;
if (align === 'start') return 0;
if (onlyOneNonOutOfStationTextInt) return 0;
return -intBoxGroupWidth / 2;
})();
return (
<g ref={ref} fontSize={30} textAnchor="middle" transform={`translate(${dx},${dy})`}>
{transfer[0].map(makeBoxElement)}
{transfer[1].length && (
{outOfStationTransfer.length > 0 && (
<>
{transfer[0].length > 0 && (
<line
Expand All @@ -566,10 +622,9 @@ const IntBoxGroup2024 = forwardRef(function IntBoxGroup2024(
<text dy="-4">出站</text>
<text dy="11">换乘</text>
</g>
{transfer[1].map(makeBoxElement)}
{outOfStationTransfer.map(makeBoxElement)}
</>
)}
{transfer[2].map(makeBoxElement)}
</g>
);
});
Expand Down
Loading
Loading