💄 Add ScrollingText component and use it in StopAreaRepr component

Update DestinationPassages component to use it.
This commit is contained in:
2023-03-05 19:20:11 +01:00
parent 546ec5a89f
commit 726efd8e8c
4 changed files with 49 additions and 35 deletions

View File

@@ -1,12 +1,11 @@
import { VoidComponent, createResource, onMount, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
import { createDateNow, getTime } from '@solid-primitives/date';
import { timeline } from '@motionone/dom';
import { AnimationOptions } from '@motionone/types';
import { Motion } from "@motionone/solid";
import { format } from "date-fns";
import { Line, TrafficStatus } from './types';
import { renderLineTransportMode, renderLinePicto } from './utils';
import { renderLineTransportMode, renderLinePicto, ScrollingText } from './utils';
import { BusinessDataContext, BusinessDataStore } from "./businessData";
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(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 (
<div class="line">
<div class="transportMode">
@@ -148,14 +129,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
</div>
{renderLinePicto(props.line)}
<div class="destination">
<svg ref={destinationViewboxRef} viewBox="0 0 600 40">
<text ref={destinationTextRef} x="0" y="50%"
dominant-baseline="middle"
font-size="40"
style={{ fill: "#000000" }}>
{props.destination}
</text>
</svg>
<ScrollingText height={40} width={600} content={props.destination} />
</div>
<div class="trafficStatus">
<svg viewBox="0 0 51 51">

View File

@@ -53,16 +53,19 @@
border-bottom: solid calc(2px);
.name {
margin-left: calc(40/1920*100%);
width: 60%;
aspect-ratio: 2.5;
display: flex;
align-items: center;
font-family: IDFVoyageur-bold;
}
.lineRepr {
// height: 100%;
width: 40%;
aspect-ratio: 2.5;
// margin-left: auto;
display: flex;
flex-direction: row;

View File

@@ -9,7 +9,7 @@ import {
} from 'leaflet';
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 { BusinessDataContext, BusinessDataStore } from "./businessData";
@@ -191,10 +191,10 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
type ByTransportModeReprs = {
mode: JSX.Element | undefined;
lines: Record<string, JSX.Element | JSX.Element[] | undefined>;
};
}
const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
const fontSize: number = 10;
const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
const appContextStore: AppContextStore | undefined = useContext(AppContextContext);
@@ -248,7 +248,9 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
return (
<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()}
</div>
);

View File

@@ -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';
@@ -129,3 +130,37 @@ export type PositionedPanel = {
// 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 >
);
}