167 lines
4.1 KiB
TypeScript
167 lines
4.1 KiB
TypeScript
import { JSX, onMount, VoidComponent } from 'solid-js';
|
|
import { timeline } from '@motionone/dom';
|
|
|
|
import { Line } from './types';
|
|
|
|
// Thanks to https://dev.to/ycmjason/how-to-create-range-in-javascript-539i
|
|
export function* range(start: number, end: number): Generator<number> {
|
|
for (let i = start; i <= end; i++) {
|
|
yield i;
|
|
}
|
|
}
|
|
|
|
const validTransportModes = ["bus", "tram", "metro", "rer", "transilien", "funicular", "ter", "unknown"];
|
|
|
|
export const TransportModeWeights: Record<string, number> = {
|
|
bus: 1,
|
|
tram: 2,
|
|
val: 3,
|
|
funicular: 4,
|
|
metro: 5,
|
|
rer: 6,
|
|
transilien: 7,
|
|
ter: 8,
|
|
};
|
|
|
|
export function getTransportModeSrc(mode: string, color: boolean = true): string | undefined {
|
|
let ret = undefined;
|
|
if (validTransportModes.includes(mode)) {
|
|
return `/carrramba-encore-rate/public/symbole_${mode}_${color ? "" : "support_fonce_"}RVB.svg`;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
export function renderLineTransportMode(line: Line): JSX.Element {
|
|
return <img src={getTransportModeSrc(line.transportMode)} />
|
|
}
|
|
|
|
function renderBusLinePicto(line: Line): JSX.Element {
|
|
return (
|
|
<div class="busLinePicto">
|
|
<svg viewBox="0 0 31.5 14">
|
|
<rect x="0" y="0" width="31.5" height="14" rx="1.5" ry="1.5" style={{ fill: `#${line.backColorHexa}` }} />
|
|
<text x="50%"
|
|
y="55%"
|
|
dominant-baseline="middle"
|
|
text-anchor="middle"
|
|
font-size="7.4"
|
|
style={{ fill: `#${line.foreColorHexa}` }}>
|
|
{line.shortName}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function renderTramLinePicto(line: Line): JSX.Element {
|
|
const lineStyle = { fill: `#${line.backColorHexa}` };
|
|
return (
|
|
<div class="tramLinePicto">
|
|
<svg viewBox="0 0 20 20">
|
|
<rect x="0" y="0" width="20" height="3" rx="1" ry="1" style={lineStyle} />
|
|
<rect x="0" y="17" width="20" height="3" rx="1" ry="1" style={lineStyle} />
|
|
<text x="50%"
|
|
y="55%"
|
|
dominant-baseline="middle"
|
|
text-anchor="middle"
|
|
font-size="11"
|
|
style={{ fill: "#00000" }}>
|
|
{line.shortName}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function renderMetroLinePicto(line: Line): JSX.Element {
|
|
return (
|
|
<div class="metroLinePicto">
|
|
<svg viewBox="0 0 20 20">
|
|
<circle cx="10" cy="10" r="10" style={{ fill: `#${line.backColorHexa}` }} />
|
|
<text x="50%"
|
|
y="55%"
|
|
dominant-baseline="middle"
|
|
text-anchor="middle"
|
|
font-size="11" style={{ fill: `#${line.foreColorHexa}` }}>
|
|
{line.shortName}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function renderTrainLinePicto(line: Line): JSX.Element {
|
|
return (
|
|
<div class="trainLinePicto">
|
|
<svg viewBox="0 0 20 20">
|
|
<rect x="0" y="0" width="20" height="20" rx="4.5" ry="4.5" style={{ fill: `#${line.backColorHexa}` }} />
|
|
<text x="50%"
|
|
y="55%"
|
|
dominant-baseline="middle"
|
|
text-anchor="middle"
|
|
font-size="11"
|
|
style={{ fill: `#${line.foreColorHexa}` }}>
|
|
{line.shortName}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function renderLinePicto(line: Line): JSX.Element {
|
|
switch (line.transportMode) {
|
|
case "bus":
|
|
case "funicular":
|
|
return renderBusLinePicto(line);
|
|
case "tram":
|
|
return renderTramLinePicto(line);
|
|
/* case "val": */
|
|
case "metro":
|
|
return renderMetroLinePicto(line);
|
|
case "transilien":
|
|
case "rer":
|
|
case "ter":
|
|
return renderTrainLinePicto(line);
|
|
}
|
|
}
|
|
|
|
export type PositionedPanel = {
|
|
position: number;
|
|
// TODO: Should be PassagesPanelComponent ?
|
|
panel: JSX.Element;
|
|
};
|
|
|
|
|
|
export const ScrollingText: VoidComponent<{ height: number, width: number, content: string }> = (props) => {
|
|
|
|
let viewBoxRef: SVGSVGElement | undefined = undefined;
|
|
let textRef: SVGTextElement | undefined = undefined;
|
|
|
|
onMount(() => {
|
|
if (viewBoxRef !== undefined && textRef !== undefined) {
|
|
const overlap = textRef.getComputedTextLength() - viewBoxRef.viewBox.baseVal.width;
|
|
if (overlap > 0) {
|
|
timeline(
|
|
[
|
|
[textRef, { x: [-overlap] }, { duration: 5 }],
|
|
[textRef, { x: [0] }, { duration: 2 }],
|
|
],
|
|
{ repeat: Infinity },
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
return (
|
|
<svg ref={viewBoxRef} viewBox={`0 0 ${props.width} ${props.height}`}>
|
|
<text
|
|
ref={textRef}
|
|
x="0%" y="55%"
|
|
dominant-baseline="middle"
|
|
font-size={`${props.height}px`}>
|
|
{props.content}
|
|
</text>
|
|
</svg >
|
|
);
|
|
}
|