Add route name transparrency effect

- Added useCameraSubscriber hook
- Added route name transparrency effect
This commit is contained in:
izawartka 2026-08-14 01:21:40 +02:00
parent 3a242bb8ad
commit e9230f5eed
4 changed files with 43 additions and 5 deletions

View File

@ -1,9 +1,13 @@
import { useRef, useCallback, useEffect } from 'react';
import { ReactSVG } from "react-svg";
import AlwaysUpText from "../text/AlwaysUpText";
import AngleHelper from "../../../helpers/angleHelper";
import { useCameraSubscriber } from '../../../hooks/useZoomPubSub';
import Constants from '../../../helpers/constants';
export default function RouteRenderer(props) {
const { object } = props;
const textRef = useRef(null);
const [startX, startY] = object.pos.toSVGCoords();
const startAngle = object.rot.y;
@ -14,6 +18,18 @@ export default function RouteRenderer(props) {
const offY = object.track_count === 2 ? -22 : -20;
const arrowOffset = - object.track_offset - 37.8;
const handleZoomTransparrency = useCallback((camera) => {
if (!textRef.current?.style || !camera) return;
const min = Constants.map.routeTextMinZoom;
const max = Constants.map.routeTextMaxZoom;
const value = (max - camera.zoom) / (max - min);
const opacity = Math.pow(Math.min(Math.max(value, 0), 1), 2);
textRef.current.style.opacity = opacity;
}, [textRef]);
useCameraSubscriber(handleZoomTransparrency);
return (<>
<g className="map-icon" transform={`translate(${endX}, ${endY}) rotate(${endAngle + 90}) translate(-80, ${arrowOffset})`}>
<ReactSVG
@ -34,8 +50,9 @@ export default function RouteRenderer(props) {
textProps={{
y: offY,
dominantBaseline: "bottom",
className: "route-text"
className: "route-text",
}}
textRef={textRef}
text={object.route_name}
/>
</g>

View File

@ -2,10 +2,20 @@ import { useCallback, useEffect, useRef } from "react";
import AngleHelper from "../../../helpers/angleHelper";
import { mapRotation$ } from "../../../services/mapRotationService";
export default function AlwaysUpText(props) {
const { baseRot, additionalRot, additionalPreRot, text, reverseAnchor, offsetX, offsetY, textProps } = props;
export default function AlwaysUpText({
baseRot,
additionalRot,
additionalPreRot,
text,
reverseAnchor,
offsetX,
offsetY,
textProps,
textRef
}) {
const gRef = useRef(null);
const textRef = useRef(null);
const ownTextRef = useRef(null);
if(!textRef) textRef = ownTextRef;
const getTransformString = useCallback((upsideDown) => {
const upsideDownRot = upsideDown ? 180 : 0;

View File

@ -15,7 +15,9 @@ const Constants = {
showDebugTrackIds: false,
mapZoomTrackDetailsThreshold: 1 / 1.44,
mapZoomObjectDetailsThreshold: 0.5,
distanceMeterMaxMovePx: 10
distanceMeterMaxMovePx: 10,
routeTextMinZoom: 1.5,
routeTextMaxZoom: 3
},
parser: {
logSceneryAfterFinished: readEnvBool('VITE_DO_LOG_SCENERY') ?? false,

View File

@ -37,6 +37,15 @@ export function useZoomPanSubscriber(setCamera, onAlign) {
}, [onAlign]);
}
export function useCameraSubscriber(onCameraUpdate) {
useEffect(() => {
const sub = camera$.subscribe((camera) => {
onCameraUpdate(camera);
});
return () => sub.unsubscribe();
}, [onCameraUpdate]);
}
export function useZoomPanEmitter() {
return {
setCamera: (x, y, rot = null, zoom = null) => {