Disable kinetic panning on mobile by default, add setting for it

This commit is contained in:
Râu Cao 2026-01-27 14:23:43 +07:00
parent 925f26ae5d
commit a0f132ec64
Signed by: raucao
GPG Key ID: 37036C356E56CC51
3 changed files with 75 additions and 2 deletions

View File

@ -4,6 +4,8 @@ import { modifier } from 'ember-modifier';
import 'ol/ol.css';
import Map from 'ol/Map.js';
import { defaults as defaultControls, Control } from 'ol/control.js';
import { defaults as defaultInteractions, DragPan } from 'ol/interaction.js';
import Kinetic from 'ol/Kinetic.js';
import View from 'ol/View.js';
import { fromLonLat, toLonLat, getPointResolution } from 'ol/proj.js';
import Overlay from 'ol/Overlay.js';
@ -21,6 +23,7 @@ export default class MapComponent extends Component {
@service storage;
@service mapUi;
@service router;
@service settings;
mapInstance;
bookmarkSource;
@ -100,6 +103,9 @@ export default class MapComponent extends Component {
rotate: true,
attribution: true,
}),
interactions: defaultInteractions({
dragPan: false, // Disable default DragPan to add a custom one
}),
});
apply(this.mapInstance, 'https://tiles.openfreemap.org/styles/liberty');
@ -353,6 +359,28 @@ export default class MapComponent extends Component {
});
});
updateInteractions = modifier(() => {
if (!this.mapInstance) return;
// Remove existing DragPan interactions
this.mapInstance.getInteractions().getArray().slice().forEach((interaction) => {
if (interaction instanceof DragPan) {
this.mapInstance.removeInteraction(interaction);
}
});
// Add new DragPan with current setting
const kinetic = this.settings.mapKinetic
? new Kinetic(-0.005, 0.05, 100)
: false;
this.mapInstance.addInteraction(
new DragPan({
kinetic: kinetic,
})
);
});
// Track the selected place from the UI Service (Router -> Map)
updateSelectedPin = modifier(() => {
const selected = this.mapUi.selectedPlace;
@ -736,6 +764,7 @@ export default class MapComponent extends Component {
<div
class="map-container {{if @isSidebarOpen 'sidebar-open'}}"
{{this.setupMap}}
{{this.updateInteractions}}
{{this.updateBookmarks}}
{{this.updateSelectedPin}}
{{this.syncPulse}}

View File

@ -4,6 +4,7 @@ import { service } from '@ember/service';
import { action } from '@ember/object';
import Icon from '#components/icon';
import eq from 'ember-truth-helpers/helpers/eq';
import not from 'ember-truth-helpers/helpers/not';
export default class SettingsPane extends Component {
@service settings;
@ -13,6 +14,11 @@ export default class SettingsPane extends Component {
this.settings.updateOverpassApi(event.target.value);
}
@action
toggleKinetic(event) {
this.settings.updateMapKinetic(event.target.value === 'true');
}
<template>
<div class="sidebar settings-pane">
<div class="sidebar-header">
@ -25,6 +31,27 @@ export default class SettingsPane extends Component {
<div class="sidebar-content">
<section class="settings-section">
<h3>Settings</h3>
<div class="form-group">
<label for="map-kinetic">Map Inertia (Kinetic Panning)</label>
<select
id="map-kinetic"
class="form-control"
{{on "change" this.toggleKinetic}}
>
<option
value="true"
selected={{if this.settings.mapKinetic "selected"}}
>
On
</option>
<option
value="false"
selected={{if (not this.settings.mapKinetic) "selected"}}
>
Off
</option>
</select>
</div>
<div class="form-group">
<label for="overpass-api">Overpass API Provider</label>
<select

View File

@ -3,6 +3,7 @@ import { tracked } from '@glimmer/tracking';
export default class SettingsService extends Service {
@tracked overpassApi = 'https://overpass.bke.ro/api/interpreter';
@tracked mapKinetic = true;
overpassApis = [
{ name: 'bke.ro', url: 'https://overpass.bke.ro/api/interpreter' },
@ -19,14 +20,30 @@ export default class SettingsService extends Service {
}
loadSettings() {
const savedApi = localStorage.getItem('marco-overpass-api');
const savedApi = localStorage.getItem('marco:overpass-api');
if (savedApi) {
this.overpassApi = savedApi;
}
const savedKinetic = localStorage.getItem('marco:map-kinetic');
if (savedKinetic !== null) {
this.mapKinetic = savedKinetic === 'true';
} else {
// Default: disabled on small screens (mobile), enabled on desktop
// We check for typical mobile width (<= 768px)
if (typeof window !== 'undefined') {
this.mapKinetic = window.innerWidth > 768;
}
}
}
updateOverpassApi(url) {
this.overpassApi = url;
localStorage.setItem('marco-overpass-api', url);
localStorage.setItem('marco:overpass-api', url);
}
updateMapKinetic(enabled) {
this.mapKinetic = enabled;
localStorage.setItem('marco:map-kinetic', String(enabled));
}
}