feat: update map anchor for station and desciprtion search

This commit is contained in:
2025-11-27 20:17:23 +03:00
parent 5481d264e0
commit c5c5f835bc
2 changed files with 45 additions and 14 deletions

View File

@@ -364,8 +364,20 @@ const computeViewTransform = (
return { scale, translation };
};
const getAnchorFromOffset = (
offsetX: number,
offsetY: number
): { x: number; y: number } => {
const length = Math.hypot(offsetX, offsetY);
const nx = offsetX / length;
const ny = offsetY / length;
return { x: (1 - nx) / 2, y: (1 - ny) / 2 };
};
const backgroundColor = toColor(BACKGROUND_COLOR);
// Override route & station color to ED1C24
const pathColor = toColor(0xed1c24);
export const WebGLRouteMapPrototype = observer(() => {
@@ -395,6 +407,7 @@ export const WebGLRouteMapPrototype = observer(() => {
const transformRef = useRef<Transform | null>(null);
const lastTransformRef = useRef<Transform | null>(null);
const [transformState, setTransformState] = useState<Transform | null>(null);
const clampTransformScale = useCallback((transform: Transform): Transform => {
const { min, max } = scaleLimitsRef.current;
const clampedScale = clamp(transform.scale, min, max);
@@ -1904,6 +1917,11 @@ export const WebGLRouteMapPrototype = observer(() => {
const labelY =
(rotatedY + offsetY) * camera.scale + camera.translation.y;
const anchor = getAnchorFromOffset(offsetX, offsetY);
const transformCss = `translate(${-anchor.x * 100}%, ${
-anchor.y * 100
}%)`;
const dpr = Math.max(1, window.devicePixelRatio || 1);
const cssX = labelX / dpr;
const cssY = labelY / dpr;
@@ -1919,8 +1937,10 @@ export const WebGLRouteMapPrototype = observer(() => {
const fontSizePercent =
routeData?.font_size ?? originalRouteData?.font_size ?? 100;
const fontScale = fontSizePercent / 100;
const primaryFontSize = 16 * fontScale;
const secondaryFontSize = 13 * fontScale;
const secondaryMarginTop = 5 * fontScale;
const backendAlign = station.align;
@@ -1972,7 +1992,7 @@ export const WebGLRouteMapPrototype = observer(() => {
position: "absolute",
left: cssX,
top: cssY,
transform: "translate(0, -50%)",
transform: transformCss,
color: "#fff",
fontFamily: "Roboto, sans-serif",
textAlign: "left",

View File

@@ -135,7 +135,10 @@ const LinkedStationsContentsInner = <
const filteredAvailableItems = availableItems.filter((item) => {
if (!searchQuery.trim()) return true;
return String(item.name).toLowerCase().includes(searchQuery.toLowerCase());
const query = searchQuery.toLowerCase();
const name = String(item.name || "").toLowerCase();
const description = String(item.description || "").toLowerCase();
return name.includes(query) || description.includes(query);
});
useEffect(() => {
@@ -483,6 +486,7 @@ const LinkedStationsContentsInner = <
<TextField
{...params}
label="Выберите остановку"
placeholder="Введите название или описание остановки..."
fullWidth
/>
)}
@@ -490,16 +494,15 @@ const LinkedStationsContentsInner = <
option.id === value?.id
}
filterOptions={(options, { inputValue }) => {
const searchWords = inputValue
.toLowerCase()
.split(" ")
.filter(Boolean);
if (!inputValue.trim()) return options;
const query = inputValue.toLowerCase();
return options.filter((option) => {
const optionWords = String(option.name)
.toLowerCase()
.split(" ");
return searchWords.every((searchWord) =>
optionWords.some((word) => word.startsWith(searchWord))
const name = String(option.name || "").toLowerCase();
const description = String(
option.description || ""
).toLowerCase();
return (
name.includes(query) || description.includes(query)
);
});
}}
@@ -534,7 +537,7 @@ const LinkedStationsContentsInner = <
label="Поиск остановок"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Введите название остановки..."
placeholder="Введите название или описание остановки..."
size="small"
/>
@@ -550,11 +553,19 @@ const LinkedStationsContentsInner = <
size="small"
/>
}
label={String(item.name)}
label={
<div className="flex justify-between items-center w-full gap-10">
<p>{String(item.name)}</p>
<p className="text-xs text-gray-500 max-w-[300px] truncate text-ellipsis">
{String(item.description)}
</p>
</div>
}
sx={{
margin: 0,
"& .MuiFormControlLabel-label": {
fontSize: "0.9rem",
width: "100%",
},
}}
/>