diff --git a/src/components/LeafletMap/controls.ts b/src/components/LeafletMap/controls.ts index abde188..c906707 100644 --- a/src/components/LeafletMap/controls.ts +++ b/src/components/LeafletMap/controls.ts @@ -1,19 +1,33 @@ import L from "leaflet"; -const TargetLocationControl = L.Control.extend({ - onAdd: function (map: L.Map, targetLocation: L.LatLngTuple) { +const GoToTargetControl = L.Control.extend({ + onAdd: function () { const locationButton = document.createElement("button"); + locationButton.id = "go-to-target-control-button"; + locationButton.textContent = "Hedefe Git"; locationButton.classList.add("custom-map-control-button"); - locationButton.addEventListener("click", () => { - map.setView(targetLocation, 18); - }); + return locationButton; + }, +}); + +const AskPermissonControl = L.Control.extend({ + onAdd: function () { + const locationButton = document.createElement("button"); + + locationButton.id = "ask-permission-control-button"; + + locationButton.textContent = "Konum İzni Ver"; + + locationButton.classList.add("custom-map-control-button"); + + locationButton.type = "button"; return locationButton; }, }); -export { TargetLocationControl }; +export { GoToTargetControl, AskPermissonControl }; diff --git a/src/components/LeafletMap/geolocation.ts b/src/components/LeafletMap/geolocation.ts new file mode 100644 index 0000000..382fc38 --- /dev/null +++ b/src/components/LeafletMap/geolocation.ts @@ -0,0 +1,59 @@ +import Toastify from "toastify-js"; +import L from "leaflet"; +import { currentLocationIcon } from "./icons"; + +function onLocationError(err: L.ErrorEvent) { + let errorMessage; + switch (err.code) { + case 1: + errorMessage = + "Konum izni alınamadı, lütfen tarayıcınızın ve cihazınızın gizlilik ayarlarını kontrol edin."; + break; + case 2: + errorMessage = + "Konumunuz tespit edilemedi, lütfen biraz sonra tekrar deneyiniz."; + break; + case 3: + errorMessage = + "Konum isteği zaman aşımına uğradı, lütfen sayfayı yenileyip tekrar deneyiniz."; + break; + default: + errorMessage = + "Konum izni alınamadı, lütfen tarayıcınızın ve cihazınızın gizlilik ayarlarını kontrol edin."; + break; + } + + Toastify({ + text: errorMessage, + duration: 3000, + gravity: "top", // `top` or `bottom` + position: "center", // `left`, `center` or `right` + stopOnFocus: true, // Prevents dismissing of toast on hover + style: { + background: "black", + borderRadius: "6px", + margin: "16px", + }, + onClick: function () {}, // Callback after click + }).showToast(); +} + +function onLocationSuccess(locationEvent: L.LocationEvent) { + const position = locationEvent.latlng; + + const currentPos = { + lat: position.lat, + lng: position.lng, + }; + + if (this._currentLocationMarker) { + this._currentLocationMarker.setLatLng(currentPos); + } else { + this._currentLocationMarker = L.marker(currentPos, { + icon: currentLocationIcon, + }); + this._currentLocationMarker.addTo(this._map); + } +} + +export { onLocationError, onLocationSuccess }; diff --git a/src/components/LeafletMap/icons.ts b/src/components/LeafletMap/icons.ts index a9c0415..5e255cf 100644 --- a/src/components/LeafletMap/icons.ts +++ b/src/components/LeafletMap/icons.ts @@ -1,11 +1,11 @@ -import { icon } from "leaflet"; +import L from "leaflet"; -var targetLocationIcon = icon({ +var targetLocationIcon = L.icon({ iconUrl: "goal.svg", iconSize: [32, 32], }); -var currentLocationIcon = icon({ +var currentLocationIcon = L.icon({ iconUrl: "blue-dot.png", iconSize: [32, 32], }); diff --git a/src/components/leaflet-map.ts b/src/components/leaflet-map.ts index f2b2ea0..cdfc7e2 100644 --- a/src/components/leaflet-map.ts +++ b/src/components/leaflet-map.ts @@ -6,12 +6,13 @@ import { customElement, property, query, state } from "lit/decorators.js"; import L, { Map } from "leaflet"; import type { LatLngTuple } from "leaflet"; import { targetLocationIcon } from "./LeafletMap/icons"; -import { TargetLocationControl } from "./LeafletMap/controls"; +import { AskPermissonControl, GoToTargetControl } from "./LeafletMap/controls"; // Styles import leafletStyles from "leaflet/dist/leaflet.css?inline"; import globalStyles from "@/styles/globals.css?inline"; import mapStyles from "@/styles/locked-page.css?inline"; +import { onLocationError, onLocationSuccess } from "./LeafletMap/geolocation"; @customElement("leaflet-map") export class LeafletMap extends LitElement { @@ -26,6 +27,12 @@ export class LeafletMap extends LitElement { @query("#mapid") _mapElement!: HTMLDivElement; + @query("#go-to-target-control-button") + _goToTargetButton!: HTMLButtonElement; + + @query("#ask-permission-control-button") + _askPermissionButton!: HTMLButtonElement; + // Properties and states @property({ type: Object }) targetLocation?: LatLngTuple; @@ -38,32 +45,47 @@ export class LeafletMap extends LitElement { @state() protected _watchingLocation = false; + private _startWatchingLocation = () => { + this._map?.locate(); + }; + firstUpdated(): void { if (!this._mapElement || !this.targetLocation) return; - var map = new Map(this._mapElement).setView(this.targetLocation, 13); + this._map = new Map(this._mapElement).setView(this.targetLocation, 13); + + this._map.on("locationerror", onLocationError); + + this._map.on("locationfound", onLocationSuccess.bind(this)); L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19, attribution: '© OpenStreetMap', - }).addTo(map); + }).addTo(this._map); // Add target location icon marker - L.marker(this.targetLocation, { icon: targetLocationIcon }).addTo(map); + L.marker(this.targetLocation, { icon: targetLocationIcon }).addTo( + this._map + ); L.circle(this.targetLocation, { color: "blue", fillColor: "#30f", fillOpacity: 0.2, radius: 50, - }).addTo(map); + }).addTo(this._map); // Add target location control - const targetLocationControl = new TargetLocationControl({ + const targetLocationControl = new GoToTargetControl({ position: "bottomleft", }); - targetLocationControl.addTo(map); + targetLocationControl.addTo(this._map); + + L.DomEvent.on(this._goToTargetButton, "click", () => { + if (!this.targetLocation || !this._map) return; + this._map.setView(this.targetLocation, 18); + }); // Check geolocation permission, if user has given permission before // start watching user location @@ -76,7 +98,22 @@ export class LeafletMap extends LitElement { break; case "denied": this._geolocationPermissionStatus = "denied"; + break; case "prompt": + if (!this._map) break; + const askPermissionControl = new AskPermissonControl({ + position: "bottomleft", + }); + askPermissionControl.onRemove = () => { + L.DomEvent.off(this._askPermissionButton); + }; + askPermissionControl.addTo(this._map); + L.DomEvent.on( + this._askPermissionButton, + "click", + this._startWatchingLocation + ); + break; default: break; }