Make CV waypoint less janky.

The CP is now draggable when there is no destination. Otherwise the
destination is draggable.
This commit is contained in:
Dan Albert 2021-05-15 13:23:56 -07:00
parent 643e5954f3
commit ed7c8c11d9

View File

@ -126,9 +126,16 @@ const SHOW_BASE_NAME_AT_ZOOM = 8;
class ControlPoint { class ControlPoint {
constructor(cp) { constructor(cp) {
this.cp = cp; this.cp = cp;
this.locationMarker = this.makeLocationMarker(); // The behavior we want is for the CP to be draggable when it has no
this.destinationMarker = this.makeDestinationMarker(); // destination, but for the destination to be draggable when it does. The
// primary marker is always shown and draggable. When a destination exists,
// the primary marker marks the destination and the secondary marker marks
// the location. When no destination exists, the primary marker marks the
// location and the secondary marker is not shown.
this.primaryMarker = this.makePrimaryMarker();
this.secondaryMarker = this.makeSecondaryMarker();
this.path = this.makePath(); this.path = this.makePath();
this.attachTooltipsAndHandlers();
this.cp.destinationChanged.connect(() => this.onDestinationChanged()); this.cp.destinationChanged.connect(() => this.onDestinationChanged());
} }
@ -136,17 +143,8 @@ class ControlPoint {
return this.cp.destination.length > 0; return this.cp.destination.length > 0;
} }
resetLocationMarker() {
// It seems that moving this without removing/adding it to the layer does
// nothing.
this.locationMarker
.removeFrom(controlPointsLayer)
.setLatLng(this.cp.position)
.addTo(controlPointsLayer);
}
hideDestination() { hideDestination() {
this.destinationMarker.removeFrom(controlPointsLayer); this.secondaryMarker.removeFrom(controlPointsLayer);
this.path.removeFrom(controlPointsLayer); this.path.removeFrom(controlPointsLayer);
} }
@ -162,17 +160,23 @@ class ControlPoint {
}); });
} }
makeLocationMarker() { detachTooltipsAndHandlers() {
// We might draw other markers on top of the CP. The tooltips from the other this.primaryMarker.unbindTooltip();
// markers are helpful so we want to keep them, but make sure the CP is this.primaryMarker.off("click");
// always the clickable thing. this.primaryMarker.off("contextmenu");
this.secondaryMarker.unbindTooltip();
this.secondaryMarker.off("click");
this.secondaryMarker.off("contextmenu");
}
attachTooltipsAndHandlers() {
this.detachTooltipsAndHandlers();
const zoom = map.getZoom(); const zoom = map.getZoom();
return L.marker(this.cp.position, { const locationMarker = this.hasDestination()
icon: iconFor(this.cp.blue), ? this.secondaryMarker
zIndexOffset: 1000, : this.primaryMarker;
draggable: this.cp.mobile, const destinationMarker = this.hasDestination() ? this.primaryMarker : null;
autoPan: true, locationMarker
})
.bindTooltip(`<h3 style="margin: 0;">${this.cp.name}</h3>`, { .bindTooltip(`<h3 style="margin: 0;">${this.cp.name}</h3>`, {
permanent: zoom >= SHOW_BASE_NAME_AT_ZOOM, permanent: zoom >= SHOW_BASE_NAME_AT_ZOOM,
}) })
@ -181,23 +185,40 @@ class ControlPoint {
}) })
.on("contextmenu", () => { .on("contextmenu", () => {
this.cp.showPackageDialog(); this.cp.showPackageDialog();
}) });
if (destinationMarker != null) {
destinationMarker.bindTooltip(`${this.cp.name} destination`);
destinationMarker.on("contextmenu", () => this.cp.cancelTravel());
destinationMarker.addTo(map);
}
}
makePrimaryMarker() {
const location = this.hasDestination()
? this.cp.destination
: this.cp.position;
// We might draw other markers on top of the CP. The tooltips from the other
// markers are helpful so we want to keep them, but make sure the CP is
// always the clickable thing.
return L.marker(location, {
icon: iconFor(this.cp.blue),
zIndexOffset: 1000,
draggable: this.cp.mobile,
autoPan: true,
})
.on("dragend", (event) => { .on("dragend", (event) => {
const marker = event.target; const marker = event.target;
const newPosition = marker.getLatLng(); const newPosition = marker.getLatLng();
this.setDestination(newPosition); this.setDestination(newPosition);
this.resetLocationMarker(); })
}); .addTo(map);
} }
makeDestinationMarker() { makeSecondaryMarker() {
const destination = this.hasDestination() ? this.cp.destination : [0, 0]; return L.marker(this.cp.position, {
return L.marker(destination, {
icon: iconFor(this.cp.blue), icon: iconFor(this.cp.blue),
zIndexOffset: 1000, zIndexOffset: 1000,
}) });
.bindTooltip(`${this.cp.name} destination`)
.on("contextmenu", () => this.cp.cancelTravel());
} }
makePath() { makePath() {
@ -210,22 +231,24 @@ class ControlPoint {
onDestinationChanged() { onDestinationChanged() {
if (this.hasDestination()) { if (this.hasDestination()) {
this.destinationMarker.setLatLng(this.cp.destination); this.primaryMarker.setLatLng(this.cp.destination);
this.destinationMarker.addTo(controlPointsLayer); this.secondaryMarker.addTo(controlPointsLayer);
this.path.setLatLngs([this.cp.position, this.cp.destination]); this.path.setLatLngs([this.cp.position, this.cp.destination]);
this.path.addTo(controlPointsLayer); this.path.addTo(controlPointsLayer);
} else { } else {
this.hideDestination(); this.hideDestination();
this.primaryMarker.setLatLng(this.cp.position);
} }
this.attachTooltipsAndHandlers();
} }
drawDestination() { drawDestination() {
this.destinationMarker.addTo(controlPointsLayer); this.secondaryMarker.addTo(controlPointsLayer);
this.path.addTo(controlPointsLayer); this.path.addTo(controlPointsLayer);
} }
draw() { draw() {
this.locationMarker.addTo(controlPointsLayer); this.primaryMarker.addTo(controlPointsLayer);
if (this.hasDestination()) { if (this.hasDestination()) {
this.drawDestination(); this.drawDestination();
} }