Add red dot, fix font, improve coordinate calculation
This commit is contained in:
parent
3ddc526cf8
commit
288fd1f7c7
BIN
frontend/assets/JetBrainsMono-Bold.woff2
Normal file
BIN
frontend/assets/JetBrainsMono-Bold.woff2
Normal file
Binary file not shown.
@ -22,6 +22,7 @@
|
|||||||
<button id="search-button" type="submit">Search</button>
|
<button id="search-button" type="submit">Search</button>
|
||||||
</form>
|
</form>
|
||||||
<img src="assets/map.jpg" id="map"><br>
|
<img src="assets/map.jpg" id="map"><br>
|
||||||
|
<div id="dot"></div>
|
||||||
<div id="info">
|
<div id="info">
|
||||||
<span id="mouse-position"></span>
|
<span id="mouse-position"></span>
|
||||||
<br>
|
<br>
|
||||||
|
30
frontend/src/coordinates.ts
Normal file
30
frontend/src/coordinates.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { Size } from "./size";
|
||||||
|
|
||||||
|
export type Coordinate = {
|
||||||
|
longitude: number;
|
||||||
|
latitude: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Position = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const scalar = { x: 8.26, y: 3.6 } as const;
|
||||||
|
const offset = { x: 6, y: 57.92 } as const;
|
||||||
|
|
||||||
|
|
||||||
|
export function convertPixelsToCoordinate(mouse: Position, map: Size): Coordinate {
|
||||||
|
return {
|
||||||
|
longitude: offset.x + mouse.x * (scalar.x / map.width),
|
||||||
|
latitude: offset.y - mouse.y * (scalar.y / map.height),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function convertCoordinateToPixels(coords: Coordinate, map: Size): Position {
|
||||||
|
return {
|
||||||
|
x: map.width * (coords.longitude - offset.x) / scalar.x,
|
||||||
|
y: map.height * (offset.y - coords.latitude) / scalar.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,20 +1,11 @@
|
|||||||
import { Throttler } from "./Throttler";
|
import { Throttler } from "./Throttler";
|
||||||
|
import { Coordinate, Position, convertPixelsToCoordinate, convertCoordinateToPixels } from "./coordinates";
|
||||||
type Position = {
|
import { Size } from "./size";
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Size = { width: number; height: number };
|
|
||||||
|
|
||||||
type Coordinate = {
|
|
||||||
longitude: number;
|
|
||||||
latitude: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ZipCodeReverseResponse = {
|
type ZipCodeReverseResponse = {
|
||||||
nr: number | null;
|
nr: number | null;
|
||||||
navn: string;
|
navn: string;
|
||||||
|
visueltcenter: number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
async function fetchZipCode({
|
async function fetchZipCode({
|
||||||
@ -35,15 +26,6 @@ async function fetchZipCode({
|
|||||||
.catch(() => null as never);
|
.catch(() => null as never);
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertPixelsToCoordinate(mouse: Position, map: Size): Coordinate {
|
|
||||||
const scalar = { x: 8, y: 3.6 };
|
|
||||||
const offset = { x: 6.2, y: 57.93 };
|
|
||||||
return {
|
|
||||||
longitude: (mouse.x / map.width) * scalar.x + offset.x,
|
|
||||||
latitude: Math.abs((mouse.y / map.height) * scalar.y - offset.y),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayMousePosition(element: HTMLParagraphElement, mouse: Position) {
|
function displayMousePosition(element: HTMLParagraphElement, mouse: Position) {
|
||||||
element.innerHTML = `Mouse position: <code>(${mouse.x}px, ${mouse.y}px)</code>`;
|
element.innerHTML = `Mouse position: <code>(${mouse.x}px, ${mouse.y}px)</code>`;
|
||||||
}
|
}
|
||||||
@ -57,12 +39,34 @@ function displayCoords(element: HTMLParagraphElement, coords: Coordinate) {
|
|||||||
function displayZipCode(
|
function displayZipCode(
|
||||||
element: HTMLParagraphElement,
|
element: HTMLParagraphElement,
|
||||||
zipCode: number | null,
|
zipCode: number | null,
|
||||||
name: string,
|
name: string | null,
|
||||||
|
center: Coordinate | null,
|
||||||
) {
|
) {
|
||||||
element.innerHTML =
|
element.innerHTML =
|
||||||
zipCode === null
|
zipCode === null
|
||||||
? `Postnummer ikke fundet`
|
? `Postnummer ikke fundet`
|
||||||
: `Postnummer: <code>${zipCode}</code>, ${name}`;
|
: `Postnummer: <code>${zipCode}</code>, ${name}`;
|
||||||
|
|
||||||
|
if (center == null) return;
|
||||||
|
|
||||||
|
const dot = document.getElementById("dot")!;
|
||||||
|
|
||||||
|
if (!zipCode) {
|
||||||
|
dot.style.display = "none";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapImg = document.getElementById("map")!;
|
||||||
|
const mapSize: Size = {
|
||||||
|
width: mapImg.clientWidth,
|
||||||
|
height: mapImg.clientHeight,
|
||||||
|
};
|
||||||
|
|
||||||
|
const position = convertCoordinateToPixels(center, mapSize);
|
||||||
|
const rect = document.getElementById("map")!.getBoundingClientRect();
|
||||||
|
dot.style.display = "block";
|
||||||
|
dot.style.left = (position.x + rect.left) + "px";
|
||||||
|
dot.style.top = (position.y + rect.top) + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMap(
|
function setupMap(
|
||||||
@ -84,7 +88,12 @@ function setupMap(
|
|||||||
displayCoords(coordsElement, coords);
|
displayCoords(coordsElement, coords);
|
||||||
fetcher.call(async () => {
|
fetcher.call(async () => {
|
||||||
const response = await fetchZipCode(coords);
|
const response = await fetchZipCode(coords);
|
||||||
displayZipCode(zipCodeElement, response.nr, response.navn);
|
displayZipCode(
|
||||||
|
zipCodeElement,
|
||||||
|
response.nr,
|
||||||
|
response.navn,
|
||||||
|
response.visueltcenter ? { longitude: response.visueltcenter[0], latitude: response.visueltcenter[1] } : null,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,13 +108,18 @@ function setupMap(
|
|||||||
displayCoords(coordsElement, coords);
|
displayCoords(coordsElement, coords);
|
||||||
fetcher.call(async () => {
|
fetcher.call(async () => {
|
||||||
const response = await fetchZipCode(coords);
|
const response = await fetchZipCode(coords);
|
||||||
displayZipCode(zipCodeElement, response.nr, response.navn);
|
displayZipCode(
|
||||||
console.log("test")
|
zipCodeElement,
|
||||||
|
response.nr,
|
||||||
|
response.navn,
|
||||||
|
response.visueltcenter ? { longitude: response.visueltcenter[0], latitude: response.visueltcenter[1] } : null,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapImg.onmouseleave = (_event: MouseEvent) => {
|
mapImg.onmouseleave = (_event: MouseEvent) => {
|
||||||
|
document.getElementById("dot")!.style.display = "none";
|
||||||
[mousePositionElement, coordsElement, zipCodeElement].forEach(
|
[mousePositionElement, coordsElement, zipCodeElement].forEach(
|
||||||
(e) => (e.innerHTML = ""),
|
(e) => (e.innerHTML = ""),
|
||||||
);
|
);
|
||||||
@ -119,10 +133,11 @@ function setupSearchBar(zipCodeElement: HTMLParagraphElement) {
|
|||||||
document.querySelector<HTMLInputElement>("#search-input")!;
|
document.querySelector<HTMLInputElement>("#search-input")!;
|
||||||
|
|
||||||
// Prevent typing letters
|
// Prevent typing letters
|
||||||
searchBar.onkeypress = (event: KeyboardEvent) => {console.log(event);
|
searchBar.onkeypress = event => {
|
||||||
event.key !== "Enter" || !isNaN(parseInt(event.key));}
|
event.key !== "Enter" || !isNaN(parseInt(event.key));
|
||||||
|
}
|
||||||
|
|
||||||
searchBar.addEventListener("submit", async (event: SubmitEvent) => {
|
searchBar.addEventListener("submit", async (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const inputValue = searchInput.value;
|
const inputValue = searchInput.value;
|
||||||
@ -137,6 +152,7 @@ function setupSearchBar(zipCodeElement: HTMLParagraphElement) {
|
|||||||
zipCodeElement,
|
zipCodeElement,
|
||||||
data.length ? parseInt(data[0]["nr"]) : null,
|
data.length ? parseInt(data[0]["nr"]) : null,
|
||||||
data.length ? data[0]["navn"] : null,
|
data.length ? data[0]["navn"] : null,
|
||||||
|
data.length ? { longitude: data[0]["visueltcenter"][0], latitude: data[0]["visueltcenter"][1] } : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
5
frontend/src/size.ts
Normal file
5
frontend/src/size.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export type Size = {
|
||||||
|
width: number;
|
||||||
|
height: number
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,11 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Jetbrains Mono";
|
font-family: "JetBrains Mono";
|
||||||
src: url("assets/JetbrainsMono-Regular.woff2");
|
src: url("assets/JetBrainsMono-Regular.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "JetBrains Mono Bold";
|
||||||
|
src: url("assets/JetBrainsMono-Bold.woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@ -40,8 +45,7 @@ main > * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: "Jetbrains Mono", monospace;
|
font-family: "JetBrains Mono Bold", monospace;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-bar {
|
#search-bar {
|
||||||
@ -109,6 +113,17 @@ code {
|
|||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dot {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid black;
|
||||||
|
filter: drop-shadow(1px 1px 2px black);
|
||||||
|
background-color: red;
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1000px) {
|
@media screen and (max-width: 1000px) {
|
||||||
main {
|
main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
Loading…
Reference in New Issue
Block a user