OnPointerOverTrigger only for touch events

I have the need to have two different interaction models based on if you have a touch device or a mouse.

Our mobile version should behave a little different from our desktop, since touch devices don’t support hover.

Is there a standard way in babylon to detect if the input is a touch device or mouse?

For all pointerevents that get triggered there is a property on the event called pointerType, which I could use.

The problem is that OnPointerOverTrigger / OnPointerOutTrigger don’t contain the underlying pointer event. (as far as I can see in when console logging the event.

How would you solve this?

cc @PolygonalSun

1 Like

As far as I know, there is no way to access the event data for a pointer event that triggers the OnPointerOverTrigger / OnPointerOutTrigger action from the action directly but you should be able to use scene.onPrePointerObservable to check for the pointerType and work from there:

scene.onPrePointerObservable.add((eventData) => {
    // Use eventData.event.pointerType to determine if it's a mouse or touch
});
2 Likes

I will check out onPrePointerObservable, thanks :slight_smile:

As for my other question?

I’m talking more about if there is a general API that the Input apis uses to detect what kind of inputs are available.

There are ways to detect what’s available via the matchMedia API, but I though if there was an api already available which tells me whats supported it would be better to use that.

As a reference, this is how you can do some checks with matchMedia

private hasHoverSupport = matchMedia('(hover: hover)').matches
private hasNoHoverSupport = matchMedia('(hover: none)').matches 

// or check for pointer type (since some devices has both touch and mouse, this will return true for such a device)
private hasTouchScreenSupport = matchMedia('(any-pointer:coarse)').matches 
1 Like

From within a pointer observable, the only way to tell if a given input is a mouse or touch input is to check its event’s pointer type. For detecting what inputs are available to receive input, using matchMedia is a good approach (we use if (matchMedia("(pointer:fine)").matches) to check for the mouse in the input system). For touch capabilities, you could also use DomManagement.IsNavigatorAvailable() && navigator.maxTouchPoints for touch (maxTouchPoints points will either be 0 or undefined if it doesn’t support touch on the given device). As far as I can recall, there is no user-facing BJS way to check what pointer devices are available, other than creating an instance of the DeviceSourceManager and using getDeviceSources to get a count.

Hey there just checking in, was your question answered? @Leon

Yes somewhat :slight_smile:

As usual there is some edge case causing problems, which means you cannot use the easy solution and have to implement some complicated logic to check if there is touch support.

I ended up with this which seems to work on all my devices including the samsung ones

let isTouchDeviceCache = null

export function isTouchDevice() {
  if (isTouchDeviceCache !== null) {
    return isTouchDeviceCache
  }

  let result = false
  if (window.PointerEvent && 'maxTouchPoints' in navigator) {
    // if Pointer Events are supported, just check maxTouchPoints
    if (navigator.maxTouchPoints > 0) {
      result = true
    }
  } else {
    // no Pointer Events...
    if (window.matchMedia && window.matchMedia('(any-pointer:coarse)').matches) {
      // check for any-pointer:coarse which mostly means touchscreen
      result = true
    } else if (window.TouchEvent || 'ontouchstart' in window) {
      // last resort - check for exposed touch events API / event handler
      result = true
    }
  }
  isTouchDeviceCache = result
  return result
}

2 Likes

Would that have been helpful in your scenario?

var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);