Compare commits
5 Commits
idfm-style
...
71e2530c01
Author | SHA1 | Date | |
---|---|---|---|
71e2530c01
|
|||
65f284bc25
|
|||
d3a689cefc
|
|||
726efd8e8c
|
|||
546ec5a89f
|
@@ -24,6 +24,7 @@
|
|||||||
"@hope-ui/solid": "^0.6.7",
|
"@hope-ui/solid": "^0.6.7",
|
||||||
"@motionone/solid": "^10.15.5",
|
"@motionone/solid": "^10.15.5",
|
||||||
"@solid-primitives/date": "^2.0.5",
|
"@solid-primitives/date": "^2.0.5",
|
||||||
|
"@solid-primitives/scroll": "^2.0.10",
|
||||||
"@stitches/core": "^1.2.8",
|
"@stitches/core": "^1.2.8",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"leaflet": "^1.9.3",
|
"leaflet": "^1.9.3",
|
||||||
|
@@ -1,27 +1,23 @@
|
|||||||
@use "_utils.scss";
|
@use "_utils.scss";
|
||||||
|
|
||||||
.passagesContainer {
|
.body {
|
||||||
|
.passagesContainer {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.displayed {
|
/* TODO: Remove the bottom border only if there are 5 displayed lines. */
|
||||||
display: block;
|
.line:last-child {
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Remove the bottom border only if there are 5 displayed lines. */
|
|
||||||
.passagesContainer .line:last-child {
|
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
/* To make up for the bottom border deletion */
|
/* To make up for the bottom border deletion */
|
||||||
padding-bottom: calc(2px);
|
padding-bottom: calc(2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Idfm: 1880x176px (margin: 0px 20px) */
|
/* Idfm: 1880x176px (margin: 0px 20px) */
|
||||||
.line {
|
.line {
|
||||||
width: calc(1880/1920*100%);
|
width: calc(1880/1920*100%);
|
||||||
height: calc(100% / 5);
|
height: calc(100% / 5);
|
||||||
margin: 0 calc(20/1920*100%);
|
margin: 0 calc(20/1920*100%);
|
||||||
@@ -32,44 +28,45 @@
|
|||||||
/* TODO: compute the border weight according to the parent height */
|
/* TODO: compute the border weight according to the parent height */
|
||||||
/* TODO: Disable border-bottom for the last .line */
|
/* TODO: Disable border-bottom for the last .line */
|
||||||
border-bottom: solid calc(2px);
|
border-bottom: solid calc(2px);
|
||||||
}
|
|
||||||
|
|
||||||
.line svg {
|
svg {
|
||||||
font-family: IDFVoyageur-bold;
|
font-family: IDFVoyageur-bold;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Idfm: 100x100px (margin: 0px 15px) */
|
}
|
||||||
.transportMode {
|
|
||||||
|
/* Idfm: 100x100px (margin: 0px 15px) */
|
||||||
|
.transportMode {
|
||||||
@extend %transportMode;
|
@extend %transportMode;
|
||||||
|
|
||||||
height: calc(100/176*100%);
|
height: calc(100/176*100%);
|
||||||
margin: 0 calc(15/1920*100%);
|
margin: 0 calc(15/1920*100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.busLinePicto {
|
.busLinePicto {
|
||||||
@extend %busLinePicto;
|
@extend %busLinePicto;
|
||||||
|
|
||||||
height: calc(70/176*100%);
|
height: calc(70/176*100%);
|
||||||
margin-right: calc(23/1920*100%);
|
margin-right: calc(23/1920*100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metroLinePicto, .tramLinePicto, .trainLinePicto {
|
.metroLinePicto, .tramLinePicto, .trainLinePicto {
|
||||||
aspect-ratio : 1 / 1;
|
aspect-ratio : 1 / 1;
|
||||||
height: calc(100/176*100%);
|
height: calc(100/176*100%);
|
||||||
margin-right: calc(23/1920*100%);
|
margin-right: calc(23/1920*100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.destination {
|
.destination {
|
||||||
height: calc(60/176*100%);
|
height: calc(60/176*100%);
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
||||||
font-family: IDFVoyageur-bold;
|
font-family: IDFVoyageur-bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trafficStatus {
|
.trafficStatus {
|
||||||
height: calc(50/176*100%);
|
height: calc(50/176*100%);
|
||||||
aspect-ratio: 35/50;
|
aspect-ratio: 35/50;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@@ -77,13 +74,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
|
||||||
|
|
||||||
.trafficStatus svg {
|
svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.firstPassage {
|
.firstPassage {
|
||||||
height: calc(100/176*100%);
|
height: calc(100/176*100%);
|
||||||
aspect-ratio: 2.5;
|
aspect-ratio: 2.5;
|
||||||
|
|
||||||
@@ -95,50 +92,49 @@
|
|||||||
|
|
||||||
/* TODO: compute the border weight according to the parent width */
|
/* TODO: compute the border weight according to the parent width */
|
||||||
border-right: solid calc(5px);
|
border-right: solid calc(5px);
|
||||||
}
|
|
||||||
|
|
||||||
.unavailableFirstPassage {
|
svg {
|
||||||
|
aspect-ratio: 215/50;
|
||||||
|
height: calc(50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unavailableFirstPassage {
|
||||||
height: calc(100/176*100%);
|
height: calc(100/176*100%);
|
||||||
aspect-ratio: calc(230/100);
|
aspect-ratio: calc(230/100);
|
||||||
margin-right: calc(30/1920*100%);
|
|
||||||
|
|
||||||
/* TODO: compute the border weight according to the parent width */
|
/* TODO: compute the border weight according to the parent width */
|
||||||
border-right: solid calc(5px);
|
border-right: solid calc(5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.firstPassage svg {
|
.secondPassage {
|
||||||
aspect-ratio: 215/50;
|
|
||||||
height: calc(1/2*100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondPassage {
|
|
||||||
height: calc(45/176*100%);
|
height: calc(45/176*100%);
|
||||||
aspect-ratio: calc(230/45);
|
aspect-ratio: calc(230/45);
|
||||||
margin-right: calc(30/1920*100%);
|
margin-right: calc(30/1920*100%);
|
||||||
}
|
|
||||||
|
|
||||||
.secondPassage svg {
|
svg {
|
||||||
font-family: IDFVoyageur-regular;
|
font-family: IDFVoyageur-regular;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.unavailableSecondPassage {
|
.unavailableSecondPassage {
|
||||||
height: calc(100/176*100%);
|
height: calc(100/176*100%);
|
||||||
aspect-ratio: calc(230/100);
|
aspect-ratio: calc(230/100);
|
||||||
margin-right: calc(30/1920*100%);
|
margin-right: calc(30/1920*100%);
|
||||||
}
|
|
||||||
|
|
||||||
.unavailableSecondPassage svg {
|
svg {
|
||||||
font-family: IDFVoyageur-regular;
|
font-family: IDFVoyageur-regular;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%withPlatformPassage {
|
%withPlatformPassage {
|
||||||
height: calc(120/176*100%);
|
height: calc(120/176*100%);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.withPlatformFirstPassage {
|
.withPlatformFirstPassage {
|
||||||
@extend %withPlatformPassage;
|
@extend %withPlatformPassage;
|
||||||
|
|
||||||
aspect-ratio: 250/120;
|
aspect-ratio: 250/120;
|
||||||
@@ -168,9 +164,9 @@
|
|||||||
font-family: IDFVoyageur-bold;
|
font-family: IDFVoyageur-bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.withPlatformSecondPassage {
|
.withPlatformSecondPassage {
|
||||||
@extend %withPlatformPassage;
|
@extend %withPlatformPassage;
|
||||||
|
|
||||||
aspect-ratio: 215/120;
|
aspect-ratio: 215/120;
|
||||||
@@ -202,4 +198,11 @@
|
|||||||
font-family: IDFVoyageur-bold;
|
font-family: IDFVoyageur-bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayed {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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">
|
||||||
|
@@ -35,7 +35,6 @@
|
|||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|
||||||
.stopPanel {
|
.stopPanel {
|
||||||
// display: None;
|
|
||||||
scroll-snap-align: center;
|
scroll-snap-align: center;
|
||||||
|
|
||||||
.stop {
|
.stop {
|
||||||
@@ -53,16 +52,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;
|
||||||
@@ -75,11 +77,6 @@
|
|||||||
height: 50%;
|
height: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.break {
|
|
||||||
flex-basis: 100%;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.linesRepresentationMatrix {
|
.linesRepresentationMatrix {
|
||||||
@extend %busLinePicto; // Use the larger picto aspect-ratio
|
@extend %busLinePicto; // Use the larger picto aspect-ratio
|
||||||
width: 75%;
|
width: 75%;
|
||||||
@@ -88,12 +85,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row;
|
flex-flow: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
// justify-content: space-around;
|
|
||||||
|
|
||||||
// .break {
|
|
||||||
// flex-basis: 100%;
|
|
||||||
// height: 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
%picto {
|
%picto {
|
||||||
margin-left: 1%;
|
margin-left: 1%;
|
||||||
@@ -123,22 +114,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.metroLinePicto {
|
.metroLinePicto {
|
||||||
@extendnd %metroLinePicto;
|
@extend %metroLinePicto;
|
||||||
@extend %singleLinePicto;
|
@extend %singleLinePicto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.busLinePicto {
|
.busLinePicto {
|
||||||
@extend %busLinePicto;
|
@extend %busLinePicto;
|
||||||
@extend %picto;
|
@extend %picto;
|
||||||
|
|
||||||
|
height: 40%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// .stop:last-child {
|
|
||||||
// border-bottom: 0;
|
|
||||||
// /* to make up for the bottom border deletion */
|
|
||||||
// padding-bottom: calc(2px);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
.displayed {
|
.displayed {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -150,93 +138,4 @@
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .lineTable {
|
|
||||||
// height: 100%;
|
|
||||||
// width: 50%;
|
|
||||||
|
|
||||||
// tr {
|
|
||||||
// height: 100%;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-flow: row;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// td {
|
|
||||||
// height: 100%;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-flow: row;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .stop {
|
|
||||||
// height: 100%;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: row;
|
|
||||||
// align-items: center;
|
|
||||||
|
|
||||||
// .lineRepr {
|
|
||||||
// height: 100%;
|
|
||||||
// aspect-ratio: 5;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: row;
|
|
||||||
// flex-wrap: wrap;
|
|
||||||
// align-items: center;
|
|
||||||
|
|
||||||
// .break {
|
|
||||||
// flex-basis: 100%;
|
|
||||||
// height: 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// .linesRepresentationMatrix {
|
|
||||||
// @extend %busLinePicto; // Use the larger picto aspect-ratio
|
|
||||||
// height: 100%;
|
|
||||||
// aspect-ratio: 3;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-flow: row;
|
|
||||||
// flex-wrap: wrap;
|
|
||||||
|
|
||||||
// .break {
|
|
||||||
// flex-basis: 100%;
|
|
||||||
// height: 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// %picto {
|
|
||||||
// margin-left: 1%;
|
|
||||||
// align-self: center;
|
|
||||||
// justify-self: center;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .transportMode {
|
|
||||||
// @extend %transportMode;
|
|
||||||
// @extend %picto;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .tramLinePicto {
|
|
||||||
// @extendnd %tramLinePicto;
|
|
||||||
// @extend %picto;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .trainLinePicto {
|
|
||||||
// @extend %trainLinePicto;
|
|
||||||
// @extend %picto;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .metroLinePicto {
|
|
||||||
// @extendnd %metroLinePicto;
|
|
||||||
// @extend %picto;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .busLinePicto {
|
|
||||||
// @extend %busLinePicto;
|
|
||||||
// @extend %picto;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@@ -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