City selection with display on a map
This commit is contained in:
+1
-1
@@ -17,7 +17,7 @@ const App: Component = () => {
|
||||
["latvia", () => <Country />],
|
||||
["database", () => <Database />],
|
||||
];
|
||||
const [getPageTitle, setPageTitle] = createSignal("cities");
|
||||
const [getPageTitle, setPageTitle] = createSignal("station");
|
||||
|
||||
const getPageContent = () => {
|
||||
const page = pages.find(p => p[0] === getPageTitle());
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
@@ -2,11 +2,12 @@ import moment from "moment";
|
||||
import { createSignal } from "solid-js";
|
||||
import { QueryResult } from "./result/QueryResult";
|
||||
|
||||
import { SelectCity } from "./SelectCity";
|
||||
import { SelectCity } from "../components/SelectCity";
|
||||
import { SelectTimeRange } from "../components/SelectTimeRange";
|
||||
|
||||
import { SelectField } from "./SelectField";
|
||||
import { SelectGranularity } from "./SelectGranularity";
|
||||
import { SelectKey } from "./SelectKey";
|
||||
import { SelectTimeRange } from "../components/SelectTimeRange";
|
||||
|
||||
const nowRounded = new Date(new Date().setMinutes(30));
|
||||
const dayAgo = moment(nowRounded).subtract(1, "days").subtract(30, "minutes").toDate();
|
||||
@@ -21,7 +22,6 @@ export function Cities() {
|
||||
|
||||
return (
|
||||
<div class="aggregator">
|
||||
<h2>Cities</h2>
|
||||
<div class="container">
|
||||
<div class="column">
|
||||
<SelectCity getCities={getCities} setCities={setCities} />
|
||||
|
||||
@@ -16,7 +16,6 @@ export function Country() {
|
||||
|
||||
return (
|
||||
<div class="fileManager">
|
||||
<h2>Latvia</h2>
|
||||
<div class="container">
|
||||
<div class="column">
|
||||
<MultiSelectField
|
||||
|
||||
@@ -24,18 +24,14 @@
|
||||
}
|
||||
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
padding-left: 20px;
|
||||
text-align: left;
|
||||
padding: 8px 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.menu li{
|
||||
display: inline;
|
||||
padding: 10px 0 10px 10px;
|
||||
cursor: pointer;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.menu li:not(:first-child)::before {
|
||||
|
||||
@@ -54,3 +54,11 @@ table tr:nth-child(odd) {
|
||||
table tr:hover {
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.visible {
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
.stationWrapper .container {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.stationWrapper .container .column {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.stationWrapper .container .column:nth-child(1) {
|
||||
padding: 0;
|
||||
flex-basis: 20%;
|
||||
background-color: white;
|
||||
min-width: 1000px;
|
||||
}
|
||||
|
||||
.stationWrapper .container .column:nth-child(2) {
|
||||
padding: 10px;
|
||||
flex-basis: 80%;
|
||||
background-color: #f2f2f2;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.stationWrapper .cities {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background-color: white;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.stationWrapper .submenu {
|
||||
padding: 5px 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
@@ -15,7 +15,6 @@ export function Database() {
|
||||
|
||||
return (
|
||||
<div class="fileManager">
|
||||
<h2>Database</h2>
|
||||
<div class="container">
|
||||
<div class="column">
|
||||
<DateList getDate={getDate} setDate={setDate} />
|
||||
|
||||
@@ -1,15 +1,51 @@
|
||||
import { Component } from "solid-js";
|
||||
import { Component, createEffect, createSignal, onMount } from "solid-js";
|
||||
|
||||
import mapUrl from "../assets/map_1000x570.webp";
|
||||
|
||||
import "../css/station.css"
|
||||
import { cityCoords } from "./cityCoords";
|
||||
import { SelectCity } from "../components/SelectCity";
|
||||
|
||||
export const Station: Component<{}> = () => {
|
||||
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>();
|
||||
const [getImg, setImg] = createSignal(new Image());
|
||||
const [getShowCities, setShowCities] = createSignal(false);
|
||||
const [getCities, setCities] = createSignal<Set<string>>(new Set(["Rīga", "Rēzekne", "Liepāja"]));
|
||||
|
||||
let ctx: CanvasRenderingContext2D | undefined;
|
||||
|
||||
onMount(() => {
|
||||
ctx = getCanvas()!.getContext("2d")!;
|
||||
|
||||
const img = new Image();
|
||||
img.onload = () => setImg(img);
|
||||
img.src = mapUrl;
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
if (!ctx || !getImg()) return;
|
||||
drawOnMap(
|
||||
ctx!,
|
||||
[getImg()],
|
||||
getCities(),
|
||||
);
|
||||
});
|
||||
|
||||
export const Station: Component<{}> = (props) => {
|
||||
return (
|
||||
<div class="fileManager">
|
||||
<h2>Station</h2>
|
||||
<div class="stationWrapper">
|
||||
<div class="container">
|
||||
<div class="column">
|
||||
1st
|
||||
<div class="submenu">
|
||||
<input
|
||||
type="button"
|
||||
value="Select stations"
|
||||
onClick={() => setShowCities(!getShowCities())}
|
||||
/>
|
||||
</div>
|
||||
<div class="column">
|
||||
2nd
|
||||
<div class={"cities " + (getShowCities() ? "visible" : "hidden")}>
|
||||
<SelectCity getCities={getCities} setCities={setCities} />
|
||||
</div>
|
||||
<canvas ref={setCanvas} width={1000} height={570} />
|
||||
</div>
|
||||
<div class="column">
|
||||
3rd
|
||||
@@ -18,3 +54,24 @@ export const Station: Component<{}> = (props) => {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function drawOnMap(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
imgArr: [HTMLImageElement],
|
||||
cities: Set<string>,
|
||||
): void {
|
||||
console.log("Draw cities");
|
||||
ctx.drawImage(imgArr[0], 0, 0);
|
||||
ctx.fillStyle = "red";
|
||||
ctx.font = "18px serif";
|
||||
cities.forEach(city => {
|
||||
const coord = cityCoords[city];
|
||||
if (!coord) return;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(coord.x, coord.y, 6, 0, 2 * Math.PI);
|
||||
const cityTextSize = ctx.measureText(city);
|
||||
ctx.fillText(city, coord.x - cityTextSize.width/2, coord.y - 6);
|
||||
ctx.fill();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
export const cityCoords: {[key: string]: { x: number, y: number}} = {
|
||||
"Ainaži": { x: 467, y: 77 },
|
||||
"Alūksne": { x: 812, y: 145 },
|
||||
"Bauska": { x: 470, y: 405 },
|
||||
"Dagda": { x: 902, y: 450 },
|
||||
"Daugavgrīva": { x: 435, y: 250 },
|
||||
"Daugavpils": { x: 780, y: 508 },
|
||||
"Dobele": { x: 340, y: 365 },
|
||||
"Gulbene": { x: 770, y: 215 },
|
||||
"Jelgava": { x: 410, y: 350 },
|
||||
"Kalnciems": { x: 390, y: 310 },
|
||||
"Kolka": { x: 250, y: 87 },
|
||||
"Kuldīga": { x: 180, y: 277 },
|
||||
"Lielpēči": { x: 530, y: 310 },
|
||||
"Liepāja": { x: 55, y: 375 },
|
||||
"Madona": { x: 720, y: 280 },
|
||||
"Mērsrags": { x: 320, y: 185 },
|
||||
"Pāvilosta": { x: 80, y: 295 },
|
||||
"Piedruja": { x: 895, y: 520 },
|
||||
"Priekuļi": { x: 590, y: 195 },
|
||||
"Rēzekne": { x: 870, y: 350 },
|
||||
"Rīga": { x: 455, y: 275 },
|
||||
"Rucava": { x: 75, y: 470 },
|
||||
"Rūjiena": { x: 590, y: 60 },
|
||||
"Saldus": { x: 240, y: 350 },
|
||||
"Sigulda": { x: 540, y: 230 },
|
||||
"Sīļi": { x: 720, y: 410 },
|
||||
"Skrīveri": { x: 580, y: 340 },
|
||||
"Skulte": { x: 485, y: 195 },
|
||||
"Stende": { x: 250, y: 235 },
|
||||
"Ventspils": { x: 123, y: 175 },
|
||||
"Vičaki": { x: 155, y: 142},
|
||||
"Zīlāni": { x: 690, y: 370 },
|
||||
"Zosēni": { x: 650, y: 250 },
|
||||
};
|
||||
Reference in New Issue
Block a user