Skip to content

Commit

Permalink
Fix tooltip showing when panning/zooming on touch device
Browse files Browse the repository at this point in the history
  • Loading branch information
milespetrov committed Feb 18, 2025
1 parent ba101da commit aa2551f
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 8 deletions.
27 changes: 27 additions & 0 deletions src/api/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ enum DefEH {
MAP_KEYUP_UPDATES_KEY_HANDLER = 'ramp_map_keyup_updates_key_handler',
MAP_MOUSE_UPDATES_COORDS = 'ramp_map_mouse_updates_coords',
MAP_MOUSE_UPDATES_MAPTIP = 'ramp_map_mouse_updates_maptip',
MAP_MOUSEDOWN_UPDATES_MAPTIP = 'ramp_map_mousedown_updates_maptip',
MAP_MOUSELEAVE_REMOVES_MAPTIP = 'ramp_map_mouseleave_removes_maptip',
MAP_RESIZE_UPDATES_SCALEBAR = 'ramp_map_resize_updates_scalebar',
MAP_SCALE_UPDATES_SCALEBAR = 'ramp_map_scale_updates_scalebar',
Expand Down Expand Up @@ -944,6 +945,32 @@ export class EventAPI extends APIScope {
throttle(50, (mapMove: MapMove) => zeHandler(mapMove)),
handlerName
);

break;

case DefEH.MAP_MOUSEDOWN_UPDATES_MAPTIP:
// update any maptip state when the mouse moves over the map
zeHandler = (mapMove: MapMove) => {
this.$iApi.geo.map.maptip.checkAtCoord({
screenX: mapMove.screenX,
screenY: mapMove.screenY
});
};

this.$iApi.event.on(
GlobalEvents.MAP_MOUSEDOWN,
throttle(50, mapMove => {
const downPoint = {
screenX: mapMove.offsetX,
screenY: mapMove.offsetY,
button: mapMove.button,
moveTime: 0
};
zeHandler(downPoint);
}),
handlerName
);

break;

case DefEH.MAP_MOUSELEAVE_REMOVES_MAPTIP:
Expand Down
22 changes: 19 additions & 3 deletions src/components/map/esri-map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
duration: [200, 200]
}"
@mousedown="mouseFocus"
@touchstart="isTouch = true"
@touchend="isTouch = false"
@keydown.up.down.left.right.prevent
></div>
</template>

<script setup lang="ts">
import { computed, inject, onBeforeUnmount, reactive, watch } from 'vue';
import { computed, inject, onBeforeUnmount, reactive, watch, ref } from 'vue';
import { useMaptipStore } from '@/stores/maptip';
import type { InstanceAPI } from '@/api';
import type { Point } from '@/geo/api';
Expand All @@ -32,6 +34,8 @@ const maptipInstance = computed(() => maptipStore.maptipInstance);
const maptipContent = computed(() => maptipStore.content);
const watchers = reactive<Array<() => void>>([]);
const isTouch = ref(false);
watchers.push(
watch(maptipPoint, () => {
if (maptipPoint.value) {
Expand All @@ -42,7 +46,8 @@ watchers.push(
const offsetX = screenPointFromMapPoint.screenX - originX;
const offsetY = originY - screenPointFromMapPoint.screenY;
maptipInstance.value.setProps({
offset: [offsetX, offsetY]
// Offset more for touch devices so tooltip is visible above finger
offset: isTouch.value ? [offsetX, offsetY + 25] : [offsetX, offsetY]
});
if (maptipContent.value && maptipContent.value !== '') {
maptipInstance.value.show();
Expand Down Expand Up @@ -74,4 +79,15 @@ const mouseFocus = () => {
};
</script>

<style lang="scss" scoped></style>
<style lang="scss">
// Prevent hidden elements from being selected on mobile when long pressing
.esri-view-surface {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
</style>
9 changes: 8 additions & 1 deletion src/fixtures/details/components/result-item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@
class="pl-3 text-left flex-grow itemName"
:content="itemName"
v-html="makeHtmlLink(itemName)"
@touchstart="isTouch = true"
@touchend="isTouch = false"
v-truncate="{
options: { placement: 'right' }
options: {
placement: 'top-start',
// Offset more for touch devices so tooltip is visible above finger
offset: () => (isTouch ? [0, 25] : [0, 0])
}
}"
:tabindex="inList ? -1 : 0"
></span>
Expand Down Expand Up @@ -111,6 +117,7 @@ const iApi = inject<InstanceAPI>('iApi')!;
const watchers = ref<Array<() => void>>([]);
const detailsStore = useDetailsStore();
const { t } = useI18n();
const isTouch = ref(false);
/**
* Icon string to display for this item
Expand Down
5 changes: 2 additions & 3 deletions src/fixtures/panguard/map-panguard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ const setup = () => {
timeoutID.value = window.setTimeout(() => {
panGuard.value!.classList.remove('pg-active');
}, 2000);
// manually scroll the page since scrolling doesn't work when moving over the map
window.scrollBy(pointer.x - x, pointer.y - y);
})
);
});
Expand Down Expand Up @@ -128,6 +125,8 @@ const setup = () => {
&.pg-active {
opacity: 1;
transition-duration: 0.3s;
pointer-events: auto !important;
touch-action: auto;
}
.pg-label {
Expand Down
6 changes: 5 additions & 1 deletion src/geo/map/maptip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ export class MaptipAPI extends APIScope {

if (!graphicHit) {
this.clear();
// If there is no graphic hit, disable the maptip. Otherwise vue-tippy will
// show the last maptip content for the previous graphic hit on touch devices when they pan/zoom.
this.maptipStore.maptipInstance.disable();
return;
}

// Get the layer
const layerInstance: LayerInstance | undefined = this.$iApi.geo.layer.getLayer(graphicHit.layerId);

Expand Down Expand Up @@ -84,6 +86,8 @@ export class MaptipAPI extends APIScope {
getAttribs: true
});

// At this point we have a graphic hit and a layer, so we can show the maptip
this.maptipStore.maptipInstance.enable();
this.setPoint(this.$iApi.geo.map.screenPointToMapPoint(screenPoint));

this.$iApi.event.emit(GlobalEvents.MAP_GRAPHICHIT, {
Expand Down

0 comments on commit aa2551f

Please sign in to comment.