Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/svg-canvas-graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ const SvgCanvas = () => {
<>
<SvgLayer
elements={elements}
selected={selected}
handlePointerDown={handlePointerDown}
handlePointerMove={handlePointerMove}
handlePointerUp={handlePointerUp}
Expand Down
83 changes: 71 additions & 12 deletions src/components/svg-layer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { LineId, MiscNodeId, StnId } from '../constants/constants';
import { Id, LineId, MiscNodeId, StnId } from '../constants/constants';
import { ExternalLineStyleAttributes, LineStyleComponentProps } from '../constants/lines';
import { MiscNodeType } from '../constants/nodes';
import { StationType } from '../constants/stations';
Expand All @@ -11,6 +11,7 @@ import { default as allStations } from './svgs/stations/stations';

interface SvgLayerProps {
elements: Element[];
selected: Set<Id>;
handlePointerDown: (node: StnId | MiscNodeId, e: React.PointerEvent<SVGElement>) => void;
handlePointerMove: (node: StnId | MiscNodeId, e: React.PointerEvent<SVGElement>) => void;
handlePointerUp: (node: StnId | MiscNodeId, e: React.PointerEvent<SVGElement>) => void;
Expand All @@ -24,7 +25,8 @@ type StyleComponent = React.FC<

const SvgLayer = React.memo(
(props: SvgLayerProps) => {
const { elements, handlePointerDown, handlePointerMove, handlePointerUp, handleEdgePointerDown } = props;
const { elements, selected, handlePointerDown, handlePointerMove, handlePointerUp, handleEdgePointerDown } =
props;

const layers = Object.fromEntries(
Array.from({ length: 21 }, (_, i) => [
Expand All @@ -42,7 +44,8 @@ const SvgLayer = React.memo(

const PreStyleComponent = lineStyles[style]?.preComponent as StyleComponent | undefined;
if (PreStyleComponent) {
layers[element.line!.attr.zIndex].pre.push(
const isSelected = selected.has(element.id);
const preComponent = (
<PreStyleComponent
key={`${element.id}.pre`}
id={element.id as LineId}
Expand All @@ -53,10 +56,16 @@ const SvgLayer = React.memo(
handlePointerDown={handleEdgePointerDown}
/>
);
layers[element.line!.attr.zIndex].pre.push(
<g key={`${element.id}.pre-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{preComponent}
</g>
);
}

const StyleComponent = (lineStyles[style]?.component ?? UnknownLineStyle) as StyleComponent;
layers[element.line!.attr.zIndex].main.push(
const isSelected = selected.has(element.id);
const component = (
<StyleComponent
key={element.id}
id={element.id as LineId}
Expand All @@ -68,9 +77,16 @@ const SvgLayer = React.memo(
/>
);

layers[element.line!.attr.zIndex].main.push(
<g key={`${element.id}-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{component}
</g>
);

const PostStyleComponent = lineStyles[style]?.postComponent as StyleComponent | undefined;
if (PostStyleComponent) {
layers[element.line!.attr.zIndex].post.push(
const isSelected = selected.has(element.id);
const postComponent = (
<PostStyleComponent
key={`${element.id}.post`}
id={element.id as LineId}
Expand All @@ -81,14 +97,20 @@ const SvgLayer = React.memo(
handlePointerDown={handleEdgePointerDown}
/>
);
layers[element.line!.attr.zIndex].post.push(
<g key={`${element.id}.post-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{postComponent}
</g>
);
}
} else if (element.type === 'station') {
const attr = element.station!;
const type = attr.type as StationType;

const PreStationComponent = allStations[type]?.preComponent;
if (PreStationComponent) {
layers[element.station!.zIndex].pre.push(
const isSelected = selected.has(element.id);
const preComponent = (
<PreStationComponent
key={`${element.id}.pre`}
id={element.id as StnId}
Expand All @@ -100,10 +122,16 @@ const SvgLayer = React.memo(
handlePointerUp={handlePointerUp}
/>
);
layers[element.station!.zIndex].pre.push(
<g key={`${element.id}.pre-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{preComponent}
</g>
);
}

const StationComponent = allStations[type]?.component ?? UnknownNode;
layers[element.station!.zIndex].main.push(
const isSelected = selected.has(element.id);
const component = (
<StationComponent
key={element.id}
id={element.id as StnId}
Expand All @@ -116,9 +144,16 @@ const SvgLayer = React.memo(
/>
);

layers[element.station!.zIndex].main.push(
<g key={`${element.id}-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{component}
</g>
);

const PostStationComponent = allStations[type]?.postComponent;
if (PostStationComponent) {
layers[element.station!.zIndex].post.push(
const isSelected = selected.has(element.id);
const postComponent = (
<PostStationComponent
key={`${element.id}.post`}
id={element.id as StnId}
Expand All @@ -130,14 +165,20 @@ const SvgLayer = React.memo(
handlePointerUp={handlePointerUp}
/>
);
layers[element.station!.zIndex].post.push(
<g key={`${element.id}.post-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{postComponent}
</g>
);
}
} else if (element.type === 'misc-node') {
const attr = element.miscNode!;
const type = attr.type as MiscNodeType;

const PreMiscNodeComponent = miscNodes[type]?.preComponent;
if (PreMiscNodeComponent) {
layers[element.miscNode!.zIndex].pre.push(
const isSelected = selected.has(element.id);
const preComponent = (
<PreMiscNodeComponent
key={`${element.id}.pre`}
id={element.id as MiscNodeId}
Expand All @@ -150,10 +191,16 @@ const SvgLayer = React.memo(
handlePointerUp={handlePointerUp}
/>
);
layers[element.miscNode!.zIndex].pre.push(
<g key={`${element.id}.pre-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{preComponent}
</g>
);
}

const MiscNodeComponent = miscNodes[type]?.component ?? UnknownNode;
layers[element.miscNode!.zIndex].main.push(
const isSelected = selected.has(element.id);
const component = (
<MiscNodeComponent
key={element.id}
id={element.id as MiscNodeId}
Expand All @@ -167,9 +214,16 @@ const SvgLayer = React.memo(
/>
);

layers[element.miscNode!.zIndex].main.push(
<g key={`${element.id}-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{component}
</g>
);

const PostMiscNodeComponent = miscNodes[type]?.postComponent;
if (PostMiscNodeComponent) {
layers[element.miscNode!.zIndex].post.push(
const isSelected = selected.has(element.id);
const postComponent = (
<PostMiscNodeComponent
key={`${element.id}.post`}
id={element.id as MiscNodeId}
Expand All @@ -182,6 +236,11 @@ const SvgLayer = React.memo(
handlePointerUp={handlePointerUp}
/>
);
layers[element.miscNode!.zIndex].post.push(
<g key={`${element.id}.post-glow`} filter={isSelected ? 'url(#selected-glow)' : undefined}>
{postComponent}
</g>
);
}
}
}
Expand All @@ -192,7 +251,7 @@ const SvgLayer = React.memo(

return jsxElements;
},
(prevProps, nextProps) => prevProps.elements === nextProps.elements
(prevProps, nextProps) => prevProps.elements === nextProps.elements && prevProps.selected === nextProps.selected
);

export default SvgLayer;
12 changes: 12 additions & 0 deletions src/components/svg-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,18 @@ const SvgWrapper = () => {
<rect x="0" y="0" width="2.5" height="2.5" fill="black" fillOpacity="50%" />
<rect x="2.5" y="2.5" width="2.5" height="2.5" fill="black" fillOpacity="50%" />
</pattern>
<filter id="selected-glow" x="-50%" y="-50%" width="200%" height="200%">
<feColorMatrix values="1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0" result="yellowGlow" />
<feGaussianBlur in="yellowGlow" stdDeviation="1" result="blur1" />
<feGaussianBlur in="yellowGlow" stdDeviation="2" result="blur2">
<animate attributeName="stdDeviation" values="1;3;1" dur="1s" repeatCount="indefinite" />
</feGaussianBlur>
<feMerge>
<feMergeNode in="blur2" />
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
{gridLines && (
<GridLines
Expand Down