Cleaned up map class names

*Cleaned up map class names and CSS
*Fixed signalbox icons having color property
This commit is contained in:
izawartka 2025-08-12 23:15:23 +02:00
parent 82d2b7d01c
commit 40ad1e678b
15 changed files with 83 additions and 127 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "visualizer2", "name": "visualizer2",
"version": "1.6.1", "version": "1.6.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "visualizer2", "name": "visualizer2",
"version": "1.6.1", "version": "1.6.2",
"dependencies": { "dependencies": {
"-": "^0.0.1", "-": "^0.0.1",
"react": "^19.1.0", "react": "^19.1.0",

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m4 19v62h92v-62zm8 8h76v46h-76z" color="#000000" fill-rule="evenodd"/> <path d="m4 19v62h92v-62zm8 8h76v46h-76z" fill-rule="evenodd"/>
<circle cx="50" cy="50" r="6"/> <circle cx="50" cy="50" r="6"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 266 B

After

Width:  |  Height:  |  Size: 250 B

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m19 19v62h62v-62zm8 8h46v46h-46z" color="#000000" fill-rule="evenodd"/> <path d="m19 19v62h62v-62zm8 8h46v46h-46z" fill-rule="evenodd"/>
<g transform="scale(.26458)" style="shape-inside:url(#rect3708);white-space:pre" aria-label="?"> <g transform="scale(.26458)" style="shape-inside:url(#rect3708);white-space:pre" aria-label="?">
<path d="m208.78 171.19c0 3.0625-0.54688 5.7969-1.6406 8.2031-1.0938 2.375-2.5312 4.4844-4.3125 6.3281-1.75 1.7812-3.7656 3.4531-6.0469 5.0156s-4.7031 3.0781-7.2656 4.5469v10.547h-8.3906v-14.297c2.0312-1.1562 4.2188-2.4219 6.5625-3.7969 2.375-1.375 4.3125-2.7656 5.8125-4.1719 1.8125-1.625 3.2188-3.2969 4.2188-5.0156 1-1.75 1.5-3.9688 1.5-6.6562 0-3.5313-1.2031-6.1563-3.6094-7.875-2.375-1.75-5.4531-2.625-9.2344-2.625-3.375 0-6.5781 0.53125-9.6094 1.5938-3 1.0625-5.375 2.1406-7.125 3.2344h-0.46875v-9.5625c2.1875-0.84375 4.9531-1.5938 8.2969-2.25 3.375-0.6875 6.5625-1.0312 9.5625-1.0312 6.7188 0 12.016 1.6406 15.891 4.9219 3.9062 3.25 5.8594 7.5469 5.8594 12.891zm-18.516 53.391h-9.5625v-9.8906h9.5625z"/> <path d="m208.78 171.19c0 3.0625-0.54688 5.7969-1.6406 8.2031-1.0938 2.375-2.5312 4.4844-4.3125 6.3281-1.75 1.7812-3.7656 3.4531-6.0469 5.0156s-4.7031 3.0781-7.2656 4.5469v10.547h-8.3906v-14.297c2.0312-1.1562 4.2188-2.4219 6.5625-3.7969 2.375-1.375 4.3125-2.7656 5.8125-4.1719 1.8125-1.625 3.2188-3.2969 4.2188-5.0156 1-1.75 1.5-3.9688 1.5-6.6562 0-3.5313-1.2031-6.1563-3.6094-7.875-2.375-1.75-5.4531-2.625-9.2344-2.625-3.375 0-6.5781 0.53125-9.6094 1.5938-3 1.0625-5.375 2.1406-7.125 3.2344h-0.46875v-9.5625c2.1875-0.84375 4.9531-1.5938 8.2969-2.25 3.375-0.6875 6.5625-1.0312 9.5625-1.0312 6.7188 0 12.016 1.6406 15.891 4.9219 3.9062 3.25 5.8594 7.5469 5.8594 12.891zm-18.516 53.391h-9.5625v-9.8906h9.5625z"/>
</g> </g>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m4 19v62h92v-62zm8 8h76v46h-76z" color="#000000" fill-rule="evenodd"/> <path d="m4 19v62h92v-62zm8 8h76v46h-76z" fill-rule="evenodd"/>
<circle cx="50" cy="58" r="6"/> <circle cx="50" cy="58" r="6"/>
<rect x="35" y="36" width="30" height="8" fill-rule="evenodd" stroke-width=".26458"/> <rect x="35" y="36" width="30" height="8" fill-rule="evenodd" stroke-width=".26458"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 337 B

View File

@ -17,118 +17,77 @@
vector-effect: non-scaling-stroke; vector-effect: non-scaling-stroke;
} }
.map svg text { .map text {
font-size: 2px; font-size: 2px;
text-shadow: 0 0 16px #000;
fill: #eee; fill: #eee;
stroke: none;
} }
.map svg text.switch-name { .map .switch-name-text {
font-size: 3px; font-size: 3px;
fill: #bbf; text-shadow: 0 0 16px #000;
} }
.map svg text.isolation-id { .map .route-text {
font-size: 72mm;
}
.map .signalbox-text {
font-size: 4px;
}
.map .isolation-id-text {
fill: #ffa; fill: #ffa;
text-shadow: 0 0 16px #000;
} }
.map svg path.isolation-end-marker { .map path.isolation-end-marker {
stroke: #ffa; stroke: #ffa;
stroke-width: 0.5px; stroke-width: 0.5px;
} }
.map svg g.track-object circle { .map g.track-object circle {
fill: #eee; fill: #eee;
} }
.map svg g.track-object text { .map g.track-object text {
fill: #eee; fill: #eee;
display: none; display: none;
text-shadow: 0 0 16px #000;
} }
.map svg g.track-object:hover text { .map g.track-object:hover text {
display: block; display: block;
} }
.map svg g.signal-icon g { .map g.platform rect {
stroke: #eee; fill: #444;
} }
.map svg g.extended-signal-icon { .map g.map-icon-stroked path,
.map g.map-icon-stroked circle,
.map g.map-icon-stroked line,
.map g.map-icon-stroked rect {
fill: none; fill: none;
stroke: #eee; stroke: #eee;
} }
.map svg g.extended-signal-icon .background { .map g.map-icon path,
fill: #111; .map g.map-icon circle,
} .map g.map-icon line,
.map g.map-icon rect {
.map svg g.route-arrow {
fill: #eee; fill: #eee;
}
.map svg g.route-name text {
fill: #eee;
font-size: 72mm;
}
.map svg g.signalbox {
fill: #eee;
}
.map svg g.signalbox text {
fill: #eee;
font-size: 4px;
}
.map svg g.sign path {
fill: #eee;
}
.map svg g.sign path.background {
fill: #111;
}
.map svg g.signal-sign path {
fill: #eee;
}
.map svg g.signal-sign path.background {
fill: #111;
}
.map svg g.signal-head-mech path {
fill: #eee;
}
.map svg g.signal-head-mech path.background {
fill: #111;
}
.map .signal-sign-text {
stroke: none; stroke: none;
} }
.map svg g.nevp path { .map g.map-icon-stroked .background,
fill: #eee; .map g.map-icon .background {
}
.map svg g.nevp path.background {
fill: #111; fill: #111;
stroke: none;
} }
.map svg g.derailer path { .map g.map-icon-stroked .with-background,
fill: #eee; .map g.map-icon .with-background {
}
.map svg g.spawn-point path {
fill: #eee;
}
.map svg g.spawn-point path.background {
fill: #111; fill: #111;
} stroke: #eee;
.map svg g.platform rect {
fill: #444;
} }

View File

@ -11,8 +11,8 @@ export default function DerailerRenderer(props) {
} }
return ( return (
<g className="derailer" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}> <g transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
<g className="derailer-icon" transform={icon_transform}> <g className="map-icon" transform={icon_transform}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/derailer.svg`} src={`${process.env.PUBLIC_URL}/assets/derailer.svg`}
wrapper='svg' wrapper='svg'
@ -28,6 +28,7 @@ export default function DerailerRenderer(props) {
additionalRot={-90} additionalRot={-90}
offsetY={-3} offsetY={-3}
text={object.getPrintableDerailerName()} text={object.getPrintableDerailerName()}
/> />
</g> </g>
); );

View File

@ -14,7 +14,7 @@ export default function IsolationIdRenderer(props) {
x={x} x={x}
y={y} y={y}
textProps={{ textProps={{
className: "isolation-id" className: "isolation-id-text"
}} }}
/>); />);
} }

View File

@ -5,7 +5,7 @@ export default function NEVPRenderer(props) {
const [x, y] = object.pos.toSVGCoords(); const [x, y] = object.pos.toSVGCoords();
return ( return (
<g className="nevp" transform={`translate(${x}, ${y}) rotate(${object.rot.y}) translate(-1.89, -1.89)`}> <g className="map-icon" transform={`translate(${x}, ${y}) rotate(${object.rot.y}) translate(-1.89, -1.89)`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/nevp.svg`} src={`${process.env.PUBLIC_URL}/assets/nevp.svg`}
wrapper='svg' wrapper='svg'

View File

@ -15,7 +15,7 @@ export default function RouteRenderer(props) {
const arrowOffset = - object.track_offset - 37.8; const arrowOffset = - object.track_offset - 37.8;
return (<> return (<>
<g className="route-arrow" transform={`translate(${endX}, ${endY}) rotate(${endAngle + 90}) translate(-80, ${arrowOffset})`}> <g className="map-icon" transform={`translate(${endX}, ${endY}) rotate(${endAngle + 90}) translate(-80, ${arrowOffset})`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/route.svg`} src={`${process.env.PUBLIC_URL}/assets/route.svg`}
wrapper='svg' wrapper='svg'
@ -25,7 +25,7 @@ export default function RouteRenderer(props) {
}} }}
/> />
</g> </g>
<g className="route-name" transform={`translate(${startX}, ${startY}) rotate(${startAngle})`}> <g transform={`translate(${startX}, ${startY}) rotate(${startAngle})`}>
<AlwaysUpText <AlwaysUpText
baseRot={startAngle} baseRot={startAngle}
additionalRot={-90} additionalRot={-90}
@ -33,7 +33,8 @@ export default function RouteRenderer(props) {
reverseAnchor={true} reverseAnchor={true}
textProps={{ textProps={{
y: offY, y: offY,
dominantBaseline: "bottom" dominantBaseline: "bottom",
className: "route-text"
}} }}
text={object.route_name} text={object.route_name}
/> />

View File

@ -14,16 +14,18 @@ export default function SignRenderer(props) {
const height = object.def.height || 1; const height = object.def.height || 1;
return ( return (
<g className="sign" transform={`translate(${x}, ${y}) rotate(${rot}) translate(${offX}, ${offY})`}> <g transform={`translate(${x}, ${y}) rotate(${rot}) translate(${offX}, ${offY})`}>
<ReactSVG <g className='map-icon'>
src={`${process.env.PUBLIC_URL}/assets/signs/${object.def.icon}`} <ReactSVG
wrapper='svg' src={`${process.env.PUBLIC_URL}/assets/signs/${object.def.icon}`}
wrapper='svg'
beforeInjection={(svg) => { beforeInjection={(svg) => {
svg.setAttribute('width', `${width}mm`); svg.setAttribute('width', `${width}mm`);
svg.setAttribute('height', `${height}mm`); svg.setAttribute('height', `${height}mm`);
}} }}
/> />
</g>
<SignTextRenderer object={object} /> <SignTextRenderer object={object} />
</g> </g>
); );

View File

@ -8,8 +8,8 @@ export default function SignalBoxRenderer(props) {
const rot = object.getFinalRotation(); const rot = object.getFinalRotation();
return ( return (
<g className="signalbox" transform={`translate(${x}, ${y})`}> <g transform={`translate(${x}, ${y})`}>
<g className="signalbox-icon" transform={`rotate(${rot}) translate(-4.725, -4.725)`}> <g className="map-icon" transform={`rotate(${rot}) translate(-4.725, -4.725)`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/signalboxes/${object.def.icon}`} src={`${process.env.PUBLIC_URL}/assets/signalboxes/${object.def.icon}`}
wrapper='svg' wrapper='svg'
@ -43,7 +43,8 @@ function SignalBoxText(props) {
additionalPreRot={rot} additionalPreRot={rot}
offsetY={6} offsetY={6}
textProps={{ textProps={{
textAnchor: 'middle' textAnchor: 'middle',
className: "signalbox-text",
}} }}
text={text} text={text}
/> />

View File

@ -45,7 +45,7 @@ function SignalIcon(props) {
const { object, pointsData } = props; const { object, pointsData } = props;
return ( return (
<g className="extended-signal-icon" strokeWidth={C.STROKE_WIDTH} strokeLinecap="round" strokeLinejoin="round"> <g className="map-icon-stroked" strokeWidth={C.STROKE_WIDTH} strokeLinecap="round" strokeLinejoin="round">
{ SignalBase(pointsData) } { SignalBase(pointsData) }
{ SignalOverheadFrame(object) } { SignalOverheadFrame(object) }
{ SignalPole(pointsData) } { SignalPole(pointsData) }
@ -83,7 +83,7 @@ function SignalHeadUnit(key, unitType, x, y) {
const r = C.HEAD_UNIT_RADIUS; const r = C.HEAD_UNIT_RADIUS;
const c = C.HEDA_UNIT_DIAGONAL; const c = C.HEDA_UNIT_DIAGONAL;
const baseCircle = <circle cx={x} cy={y} r={r} className='background' />; const baseCircle = <circle cx={x} cy={y} r={r} className='with-background' />;
switch(unitType) { switch(unitType) {
case SignalElementsEnums.UnitType.RED: case SignalElementsEnums.UnitType.RED:
@ -170,7 +170,7 @@ function SignalHeadTOP(object, {headOffsetY}) {
} }
function SignalHomeMechArm(y, rot) { function SignalHomeMechArm(y, rot) {
return <g transform={`translate(0 ${y}) rotate(${rot}) translate(${C.MECH_ARM_X_OFF - 1.89}, -1.89)`}> return <g transform={`translate(0 ${y}) rotate(${rot}) translate(${C.MECH_ARM_X_OFF - 1.89}, -1.89)`} className='map-icon'>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/mech_signals/arm.svg`} src={`${process.env.PUBLIC_URL}/assets/mech_signals/arm.svg`}
wrapper='svg' wrapper='svg'
@ -183,7 +183,7 @@ function SignalHomeMechArm(y, rot) {
} }
function SignalCustomMechHead(y, fileName) { function SignalCustomMechHead(y, fileName) {
return <g transform={`translate(-1.89, ${y - 1.89})`}> return <g transform={`translate(-1.89, ${y - 1.89})`} className='map-icon'>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/mech_signals/${fileName}`} src={`${process.env.PUBLIC_URL}/assets/mech_signals/${fileName}`}
wrapper='svg' wrapper='svg'
@ -200,31 +200,23 @@ function SignalMechHead(object, {headOffsetY}) {
switch(mechType) { switch(mechType) {
case SignalElementsEnums.MechType.HOME_SINGLE: case SignalElementsEnums.MechType.HOME_SINGLE:
return <g className="signal-head-mech"> return SignalHomeMechArm(headOffsetY, 0);
{ SignalHomeMechArm(headOffsetY, 0) }
</g>
case SignalElementsEnums.MechType.HOME_DOUBLE: case SignalElementsEnums.MechType.HOME_DOUBLE:
return <g className="signal-head-mech"> return <>
{ SignalHomeMechArm(headOffsetY, 0) } { SignalHomeMechArm(headOffsetY, 0) }
{ SignalHomeMechArm(headOffsetY + C.MECH_SECOND_ARM_OFFSET, -90) } { SignalHomeMechArm(headOffsetY + C.MECH_SECOND_ARM_OFFSET, -90) }
</g> </>;
case SignalElementsEnums.MechType.SHUNTING: case SignalElementsEnums.MechType.SHUNTING:
return <g className="signal-head-mech"> return SignalCustomMechHead(headOffsetY, 'shunting_head.svg');
{ SignalCustomMechHead(headOffsetY, 'shunting_head.svg') }
</g>
case SignalElementsEnums.MechType.DISTANT_SINGLE: case SignalElementsEnums.MechType.DISTANT_SINGLE:
return <g className="signal-head-mech"> return SignalCustomMechHead(headOffsetY, 'distant_head.svg');
{ SignalCustomMechHead(headOffsetY, 'distant_head.svg') }
</g>
case SignalElementsEnums.MechType.DISTANT_DOUBLE: case SignalElementsEnums.MechType.DISTANT_DOUBLE:
return <g className="signal-head-mech"> return <>
{ SignalCustomMechHead(headOffsetY, 'distant_head.svg') } { SignalCustomMechHead(headOffsetY, 'distant_head.svg') }
{ SignalCustomMechHead(headOffsetY + C.MECH_SECOND_ARM_OFFSET, 'distant_arm.svg') } { SignalCustomMechHead(headOffsetY + C.MECH_SECOND_ARM_OFFSET, 'distant_arm.svg') }
</g> </>;
case SignalElementsEnums.MechType.STOP: case SignalElementsEnums.MechType.STOP:
return <g className="signal-head-mech"> return SignalCustomMechHead(headOffsetY, 'stop_head.svg');
{ SignalCustomMechHead(headOffsetY, 'stop_head.svg') }
</g>
default: default:
return null; return null;
} }
@ -234,7 +226,7 @@ function SignalBar(y, isYellow, key = 0) {
const yellowOff = isYellow ? C.BAR_HALF_H : 0; const yellowOff = isYellow ? C.BAR_HALF_H : 0;
return <g key={key}> return <g key={key}>
<rect x={-C.BAR_HALF_W} y={y-C.BAR_HALF_H} width={C.BAR_HALF_W*2} height={C.BAR_HALF_H*2} className='background' />; <rect x={-C.BAR_HALF_W} y={y-C.BAR_HALF_H} width={C.BAR_HALF_W*2} height={C.BAR_HALF_H*2} className='with-background' />;
<line x1={-yellowOff} y1={y-C.BAR_HALF_H} x2={yellowOff} y2={y+C.BAR_HALF_H} />; <line x1={-yellowOff} y1={y-C.BAR_HALF_H} x2={yellowOff} y2={y+C.BAR_HALF_H} />;
</g> </g>
} }
@ -282,7 +274,7 @@ function SignalSign(id, y) {
const def = DefinedSignalSigns[id]; const def = DefinedSignalSigns[id];
if(!def) return null; if(!def) return null;
return <g key={id} className="signal-sign" transform={`translate(-1.89, ${y - 1.89})`}> return <g key={id} className="map-icon" transform={`translate(-1.89, ${y - 1.89})`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/signal_signs/${def.icon}`} src={`${process.env.PUBLIC_URL}/assets/signal_signs/${def.icon}`}
wrapper='svg' wrapper='svg'

View File

@ -7,8 +7,8 @@ export default function SignalStandardRenderer(props) {
const name = showOriginalName ? object.name?.trim() : object.getPrintableSignalName(); const name = showOriginalName ? object.name?.trim() : object.getPrintableSignalName();
return ( return (
<g className="signal" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}> <g transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
<g className="signal-icon" transform={`translate(-1.89, -1.89)`}> <g className="map-icon" transform={`translate(-1.89, -1.89)`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/signal.svg`} src={`${process.env.PUBLIC_URL}/assets/signal.svg`}
wrapper='svg' wrapper='svg'

View File

@ -6,8 +6,8 @@ export default function SpawnPointRenderer(props) {
const [x, y] = object.pos.toSVGCoords(); const [x, y] = object.pos.toSVGCoords();
return ( return (
<g className="spawn-point" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}> <g transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
<g className="signal-icon" transform={`rotate(180) translate(-2.835, -2.835)`}> <g className="map-icon" transform={`rotate(180) translate(-2.835, -2.835)`}>
<ReactSVG <ReactSVG
src={`${process.env.PUBLIC_URL}/assets/spawn.svg`} src={`${process.env.PUBLIC_URL}/assets/spawn.svg`}
wrapper='svg' wrapper='svg'

View File

@ -10,7 +10,7 @@ export default function SwitchNameRenderer(props) {
x={x} x={x}
y={y} y={y}
textProps={{ textProps={{
className: "switch-name" className: "switch-name-text"
}} }}
/>; />;
} }