mirror of
https://github.com/cjdenio/uta-trax-api.git
synced 2026-10-03 16:06:19 +00:00
much new
This commit is contained in:
2 files changed
+81
-44
No files matched your search
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<title>UTA Vehicle Tracker</title>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||||
@@ -17,6 +19,10 @@
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.leaflet-marker-icon:has(.vehicle) {
|
||||||
|
transition: transform 300ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
+75
-44
@@ -1,9 +1,11 @@
|
|||||||
import * as shapes from "./shapes.js";
|
|
||||||
import protobuf from "https://cdn.jsdelivr.net/npm/protobufjs@8.0.0/dist/protobuf.js/+esm";
|
import protobuf from "https://cdn.jsdelivr.net/npm/protobufjs@8.0.0/dist/protobuf.js/+esm";
|
||||||
import * as L from "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet-src.esm.js";
|
import * as L from "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet-src.esm.js";
|
||||||
import stations from "./stations.js"
|
|
||||||
import Alpine from "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/module.esm.min.js";
|
import Alpine from "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/module.esm.min.js";
|
||||||
|
|
||||||
|
import * as shapes from "./shapes.js";
|
||||||
|
import stations from "./stations.js"
|
||||||
|
|
||||||
|
/** @type {number} */
|
||||||
let lastUpdated;
|
let lastUpdated;
|
||||||
|
|
||||||
function displayLastUpdated() {
|
function displayLastUpdated() {
|
||||||
@@ -122,41 +124,10 @@ protobuf.load("/schema.proto").then((root) => {
|
|||||||
|
|
||||||
let bannerVisible = false
|
let bannerVisible = false
|
||||||
|
|
||||||
async function reload() {
|
let currentVehicles = new Map()
|
||||||
const bin = await fetch("/api").then((r) => r.arrayBuffer());
|
|
||||||
const { vehicles, info } = root
|
|
||||||
.lookupType("VehicleFeed")
|
|
||||||
.decode(new Uint8Array(bin));
|
|
||||||
|
|
||||||
lastUpdated = info.lastUpdate
|
function renderVehicleIcon(vehicle) {
|
||||||
displayLastUpdated()
|
return L.divIcon({
|
||||||
|
|
||||||
populateTotals(vehicles)
|
|
||||||
if (vehicles.length == 0) {
|
|
||||||
if (!bannerVisible) {
|
|
||||||
document.getElementById("banner").classList.remove("hidden")
|
|
||||||
bannerVisible = true
|
|
||||||
map.invalidateSize()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (bannerVisible) {
|
|
||||||
document.getElementById("banner").classList.add("hidden")
|
|
||||||
bannerVisible = false
|
|
||||||
map.invalidateSize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render vehicles on map
|
|
||||||
clearMap();
|
|
||||||
|
|
||||||
vehicles.forEach((vehicle) => {
|
|
||||||
L.marker([vehicle.lat, vehicle.lon], {
|
|
||||||
zIndexOffset:
|
|
||||||
vehicle.route.type == RouteType.TRAM ||
|
|
||||||
vehicle.route.type == RouteType.RAIL
|
|
||||||
? 4000
|
|
||||||
: 3000,
|
|
||||||
icon: L.divIcon({
|
|
||||||
className: "",
|
className: "",
|
||||||
html: `<div class="vehicle ${
|
html: `<div class="vehicle ${
|
||||||
vehicle.route.type == RouteType.BUS &&
|
vehicle.route.type == RouteType.BUS &&
|
||||||
@@ -181,9 +152,61 @@ protobuf.load("/schema.proto").then((root) => {
|
|||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</div>`,
|
</div>`,
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
.addTo(
|
}
|
||||||
|
|
||||||
|
function renderVehicle(vehicle) {
|
||||||
|
return L.marker([vehicle.lat, vehicle.lon], {
|
||||||
|
zIndexOffset:
|
||||||
|
vehicle.route.type == RouteType.TRAM ||
|
||||||
|
vehicle.route.type == RouteType.RAIL
|
||||||
|
? 4000
|
||||||
|
: 3000,
|
||||||
|
icon: renderVehicleIcon(vehicle),
|
||||||
|
})
|
||||||
|
.bindPopup(
|
||||||
|
`<b>${routeDesignator(vehicle.route)}</b> to <b>${vehicle.headsign.replace(
|
||||||
|
/^to /i,
|
||||||
|
""
|
||||||
|
)}</b>${vehicle.nearestStation ? `<br />@ ${vehicle.nearestStation?.name}` : ""}<br /><br /><small>vehicle #: ${vehicle.id}</small>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reload() {
|
||||||
|
const bin = await fetch("/api").then((r) => r.arrayBuffer());
|
||||||
|
const { vehicles, info } = root
|
||||||
|
.lookupType("VehicleFeed")
|
||||||
|
.decode(new Uint8Array(bin));
|
||||||
|
|
||||||
|
lastUpdated = info.lastUpdate
|
||||||
|
displayLastUpdated()
|
||||||
|
|
||||||
|
populateTotals(vehicles)
|
||||||
|
if (vehicles.length == 0) {
|
||||||
|
if (!bannerVisible) {
|
||||||
|
document.getElementById("banner").classList.remove("hidden")
|
||||||
|
bannerVisible = true
|
||||||
|
map.invalidateSize()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bannerVisible) {
|
||||||
|
document.getElementById("banner").classList.add("hidden")
|
||||||
|
bannerVisible = false
|
||||||
|
map.invalidateSize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const seenVehicleIds = new Set()
|
||||||
|
|
||||||
|
vehicles.forEach((vehicle) => {
|
||||||
|
seenVehicleIds.add(vehicle.id)
|
||||||
|
|
||||||
|
if (currentVehicles.has(vehicle.id)) { // if this vehicle is already on the map, update its location
|
||||||
|
currentVehicles.get(vehicle.id).marker.setLatLng([vehicle.lat, vehicle.lon])
|
||||||
|
currentVehicles.get(vehicle.id).marker.setIcon(renderVehicleIcon(vehicle))
|
||||||
|
} else {
|
||||||
|
const marker = renderVehicle(vehicle)
|
||||||
|
marker.addTo(
|
||||||
["92235", "3686", "87711"].includes(vehicle.route.id)
|
["92235", "3686", "87711"].includes(vehicle.route.id)
|
||||||
? brtLayer
|
? brtLayer
|
||||||
: vehicle.route.type == RouteType.TRAM
|
: vehicle.route.type == RouteType.TRAM
|
||||||
@@ -191,14 +214,22 @@ protobuf.load("/schema.proto").then((root) => {
|
|||||||
: vehicle.route.type == RouteType.RAIL
|
: vehicle.route.type == RouteType.RAIL
|
||||||
? frontRunnerLayer
|
? frontRunnerLayer
|
||||||
: busLayer
|
: busLayer
|
||||||
)
|
|
||||||
.bindPopup(
|
|
||||||
`<b>${routeDesignator(vehicle.route)}</b> to <b>${vehicle.headsign.replace(
|
|
||||||
/^to /i,
|
|
||||||
""
|
|
||||||
)}</b>${vehicle.nearestStation ? `<br />@ ${vehicle.nearestStation?.name}` : ""}<br /><br /><small>vehicle #: ${vehicle.id}</small>`
|
|
||||||
);
|
);
|
||||||
|
currentVehicles.set(vehicle.id, {
|
||||||
|
vehicle,
|
||||||
|
marker,
|
||||||
|
})
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// remove any vehicles that should be removed
|
||||||
|
for (const key of currentVehicles.keys()) {
|
||||||
|
if (!seenVehicleIds.has(key)) {
|
||||||
|
console.log(`removing vehicle from route ${currentVehicles.get(key).vehicle.route.shortName}`)
|
||||||
|
currentVehicles.get(key).marker.remove()
|
||||||
|
currentVehicles.delete(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
|
|||||||
Reference in new issue
Block a user