💄 Add ScrollingText component and use it in StopAreaRepr component
Update DestinationPassages component to use it.
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
import { VoidComponent, createResource, onMount, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
|
import { VoidComponent, createResource, onMount, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
|
||||||
import { createDateNow, getTime } from '@solid-primitives/date';
|
import { createDateNow, getTime } from '@solid-primitives/date';
|
||||||
import { timeline } from '@motionone/dom';
|
|
||||||
import { AnimationOptions } from '@motionone/types';
|
import { AnimationOptions } from '@motionone/types';
|
||||||
import { Motion } from "@motionone/solid";
|
import { Motion } from "@motionone/solid";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
||||||
import { Line, TrafficStatus } from './types';
|
import { Line, TrafficStatus } from './types';
|
||||||
import { renderLineTransportMode, renderLinePicto } from './utils';
|
import { renderLineTransportMode, renderLinePicto, ScrollingText } from './utils';
|
||||||
import { BusinessDataContext, BusinessDataStore } from "./businessData";
|
import { BusinessDataContext, BusinessDataStore } from "./businessData";
|
||||||
|
|
||||||
import "./passagesPanel.scss";
|
import "./passagesPanel.scss";
|
||||||
@@ -123,24 +122,6 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
|
|||||||
// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
|
// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
|
||||||
const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };
|
const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };
|
||||||
|
|
||||||
let destinationViewboxRef: SVGSVGElement | undefined = undefined;
|
|
||||||
let destinationTextRef: SVGTextElement | undefined = undefined;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
if (destinationViewboxRef !== undefined && destinationTextRef !== undefined) {
|
|
||||||
const overlap = destinationTextRef.getComputedTextLength() - destinationViewboxRef.viewBox.baseVal.width;
|
|
||||||
if (overlap > 0) {
|
|
||||||
timeline(
|
|
||||||
[
|
|
||||||
[destinationTextRef, { x: [-overlap] }, { duration: 5 }],
|
|
||||||
[destinationTextRef, { x: [0] }, { duration: 2 }],
|
|
||||||
],
|
|
||||||
{ repeat: Infinity },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="transportMode">
|
<div class="transportMode">
|
||||||
@@ -148,14 +129,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
|
|||||||
</div>
|
</div>
|
||||||
{renderLinePicto(props.line)}
|
{renderLinePicto(props.line)}
|
||||||
<div class="destination">
|
<div class="destination">
|
||||||
<svg ref={destinationViewboxRef} viewBox="0 0 600 40">
|
<ScrollingText height={40} width={600} content={props.destination} />
|
||||||
<text ref={destinationTextRef} x="0" y="50%"
|
|
||||||
dominant-baseline="middle"
|
|
||||||
font-size="40"
|
|
||||||
style={{ fill: "#000000" }}>
|
|
||||||
{props.destination}
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="trafficStatus">
|
<div class="trafficStatus">
|
||||||
<svg viewBox="0 0 51 51">
|
<svg viewBox="0 0 51 51">
|
||||||
|
@@ -53,16 +53,19 @@
|
|||||||
border-bottom: solid calc(2px);
|
border-bottom: solid calc(2px);
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
margin-left: calc(40/1920*100%);
|
||||||
width: 60%;
|
width: 60%;
|
||||||
|
aspect-ratio: 2.5;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
font-family: IDFVoyageur-bold;
|
font-family: IDFVoyageur-bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lineRepr {
|
.lineRepr {
|
||||||
// height: 100%;
|
|
||||||
width: 40%;
|
width: 40%;
|
||||||
aspect-ratio: 2.5;
|
aspect-ratio: 2.5;
|
||||||
// margin-left: auto;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@@ -9,7 +9,7 @@ import {
|
|||||||
} from 'leaflet';
|
} from 'leaflet';
|
||||||
|
|
||||||
import { Stop } from './types';
|
import { Stop } from './types';
|
||||||
import { PositionedPanel, renderLineTransportMode, renderLinePicto, TransportModeWeights } from './utils';
|
import { PositionedPanel, renderLineTransportMode, renderLinePicto, ScrollingText, TransportModeWeights } from './utils';
|
||||||
|
|
||||||
import { AppContextContext, AppContextStore } from "./appContext";
|
import { AppContextContext, AppContextStore } from "./appContext";
|
||||||
import { BusinessDataContext, BusinessDataStore } from "./businessData";
|
import { BusinessDataContext, BusinessDataStore } from "./businessData";
|
||||||
@@ -191,10 +191,10 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
|
|||||||
type ByTransportModeReprs = {
|
type ByTransportModeReprs = {
|
||||||
mode: JSX.Element | undefined;
|
mode: JSX.Element | undefined;
|
||||||
lines: Record<string, JSX.Element | JSX.Element[] | undefined>;
|
lines: Record<string, JSX.Element | JSX.Element[] | undefined>;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
|
const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
|
||||||
|
const fontSize: number = 10;
|
||||||
|
|
||||||
const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
|
const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
|
||||||
const appContextStore: AppContextStore | undefined = useContext(AppContextContext);
|
const appContextStore: AppContextStore | undefined = useContext(AppContextContext);
|
||||||
@@ -248,7 +248,9 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="stop" onClick={() => setDisplayedStops([props.stop])}>
|
<div class="stop" onClick={() => setDisplayedStops([props.stop])}>
|
||||||
<div class="name">{props.stop.name}</div>
|
<div class="name" >
|
||||||
|
<ScrollingText height={fontSize} width={100} content={props.stop.name} />
|
||||||
|
</div>
|
||||||
{lineReprs()}
|
{lineReprs()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { JSX } from 'solid-js';
|
import { JSX, onMount, VoidComponent } from 'solid-js';
|
||||||
|
import { timeline } from '@motionone/dom';
|
||||||
|
|
||||||
import { Line } from './types';
|
import { Line } from './types';
|
||||||
|
|
||||||
@@ -129,3 +130,37 @@ export type PositionedPanel = {
|
|||||||
// TODO: Should be PassagesPanelComponent ?
|
// TODO: Should be PassagesPanelComponent ?
|
||||||
panel: JSX.Element;
|
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 >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user