Babylonjs virtual joystick and scene actions

have a babylon.js project. I am using virtual joystick.

` var leftJoystick = new BABYLON.VirtualJoystick(true);

BABYLON.VirtualJoystick.Canvas.style.zIndex = "4";

var movespeed = 5
scene.onBeforeRenderObservable.add(()=>{
    if(leftJoystick.pressed){
       const moveX = leftJoystick.deltaPosition.x * (engine.getDeltaTime()/1000) * movespeed;
       const moveZ = leftJoystick.deltaPosition.y * (engine.getDeltaTime()/1000) * movespeed;
        camera.position.x+=moveX
        camera.position.z+=moveZ
    }
})`

but i don’t click another models how to solve this problem.

I tried define touch border with html and css but not worked.

The VirtualJoystick overlaps with your UI. You can try to hide it on release and show it again when you touch something other than your models.

Yes i tried but i didn’t find the solution

When you press F12 to see DevTools in browser, take a look at second canvas:

<canvas width="965" height="912" touch-action="none" style="width: 100%; height: 100%; position: absolute; background-color: transparent; top: 0px; left: 0px; z-index: 5; touch-action: none;"></canvas>

It have z-index: 5. You can change z-index to -1 on !stick.pressed. And set listeners on your main canvas which bring back z-index for virtual joystick’s canvas.
I don’t like this solution, sounds like a hack. Need to think more.

1 Like

Hi, I was inspired by your issue because it also concerns me. The fact that VirtualJoystick creates an additional canvas that overlays the main renderCanvas of our BabylonJS application is undoubtedly a problem for many. I decided to extend my add-on to VirtualJoystick a little further and added two features. :slight_smile: You can go through the script, see what you need, and apply my ideas to your application. For simplicity, you can just use the CanvasManager and toggle it when needed in your application. Or you can use the Swipe Switcher add-on and swipe up from the bottom of the screen to display the virtual joystick panel, and swipe down from the bottom of the screen to hide it. This way, you can hide the joysticks during usage to make the area with your main Canvas accessible for clicks.

Look what I just added now:

const stick = new TouchStick(true)
stick.enableSwipeSwitcher(scene)

This code will work assuming that the canvas of your application has an id, while the VirtualJoystick canvas does not. Thus, I obtain the joystick canvas using the following method:

getCanvasWithoutId() {
    const canvases = document.body.getElementsByTagName('canvas')
    for (let i = 0; i < canvases.length; i++) {
      if (!canvases[i].id) {
        return canvases[i]
      }
    }
    return null
}

Then, I pass BABYLON.Scene as a parameter to the class, and from the scene, I can easily get the application canvas using scene.getEngine().getRenderingCanvas(). Having obtained two canvases, I then need to switch them based on some events. I attach listeners to both canvases. Shrinking or expanding the joystick canvas based on swipes at the bottom is achieved through the following methods:

show(gradient: boolean = false) {
    const canvas = this.getCanvasWithoutId()
    this.visible = true
    if (canvas) {
      this.setupStickCanvasListener()
      this.removeAppCanvasListener()
      if (!gradient) {
        canvas.style.zIndex = '5'
        return
      }
      canvas.style.height = '100%'
      canvas.style.top = 'inherit'
      canvas.style.bottom = '0'
      canvas.style.background =
          'linear-gradient(to top, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 100%)'
      canvas.style.transition =
          'height 0.5s ease, bottom 0.5s ease, background 0.5s ease'
    }
}

hide(gradient: boolean = false) {
    const canvas = this.getCanvasWithoutId()
    this.visible = false
    if (canvas) {
      this.setupAppCanvasListener()
      this.removeStickCanvasListener()
      if (!gradient) {
        canvas.style.zIndex = '-1'
        return
      }
      canvas.style.top = 'inherit'
      canvas.style.bottom = '0'
      canvas.style.height = '0%'
      canvas.style.background =
          'linear-gradient(to top, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 100%)'
      canvas.style.transition =
          'height 0.5s ease, bottom 0.5s ease, background 0.5s ease'
    }
}

Anyway it’s not an perfect solution, hope you’ll find something useful from it to customize your app.

Thank you for helps I will try.