aframevr / aframe

:a: Web framework for building virtual reality experiences.
https://aframe.io/
MIT License
16.46k stars 3.92k forks source link

Display helpful message (to rotate orientation twice) when loading a scene in iOS/Safari in Landscape Mode #2577

Open derhuebiii opened 7 years ago

derhuebiii commented 7 years ago

Description: When using the fullscreen mode in Safari/iOS, the navigation bar stays active.

I am raising this as an issue here, as the WebVR Polyfill Examples are working on iOS, but aframe does not. So it doesn't seem to be an iOS problem.

I was investigating why it is not working with aframe, but the only difference I found is that the examples are calling requestPresent handing over a canvas object. vrDisplay.requestPresent([{ source: webglCanvas }]).then(function () { ...

Can this be the reason? I tried to add a canvas and call with the source, but it didn't work...

Also interesting the comment:

  function onVRRequestPresent () {
    // This can only be called in response to a user gesture.

Is this ensured in aframe?

WebVR-Examples: https://webvr.info/samples/ WebVR-Example-Code: https://github.com/toji/webvr.info/blob/master/samples/03-vr-presentation.html

derhuebiii commented 7 years ago

I checked what happens if you go to Fullscreen with the WebVR sample, it wraps a fullscreen wraper div around the canvas and also changes the canvas size. Tried to do this with a listener when entering VR, but it didn't work:

    document.addEventListener("enter-vr", function() {

      this.fullscreenWrapper_ = document.createElement('div');

      var cssProperties = [
        'height: ' + Math.min(screen.height, screen.width) + 'px !important',
        'top: 0 !important',
        'left: 0 !important',
        'right: 0 !important',
        'border: 0',
        'margin: 0',
        'padding: 0',
        'z-index: 999999 !important',
        'position: fixed',
      ];
      this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';');
      this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper');

    this.fullscreenElement_ = document.getElementById("ascene");
    console.log(document.getElementById("ascene"));
    var parent = this.fullscreenElement_.parentElement;
    parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_);
    parent.removeChild(this.fullscreenElement_);
    this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild);
    this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style');

}

derhuebiii commented 7 years ago

I found a workaround (don't know how and if you want to implement this though):

3 things to do:

Change CSS for HTML and BODY and set a-scene fixed to 0

    body {
      overflow: scroll !important
    }

    html {
      position: relative !important
    }

    a-scene {
      position: fixed;
      top: 0;
      left: 0
    }

Add a div in body that makes the page larger

  <div style="height:150vh;">

  </div>

Add an eventListener that scrolls the page down on EnterVR:

        document.addEventListener("enter-vr", function() {
          window.scrollTo(0,document.body.scrollHeight);
        });

Now there is no menu bar anymore. You can still scroll up, but at least it has the same effect as fullscreen :)

jeroenVerdonschot commented 7 years ago

@derhuebiii

I tried your workaround but nothing happens. Bars a still there. Do I need place the event listener on a special place in my HTML?

You put html twice in your css. This can be one right? Or has one of the htmls be somethings else.

Thanks for investigating this!

derhuebiii commented 7 years ago

@rambambulli HTML in CSS only needs to be there once, it's a copy paste error.

The listener shouldn't matter where as long as it's loaded when pressing the VR Button.

Worth to mention my header looks like this:

<html>
<head>
    <title>My A-Frame Scene</title>
    <meta name="viewport" content="width = device-width, initial-scale = 1.0, minimum-scale = 1, maximum-scale = 1, user-scalable = no" />

    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />

You could check two things:

  1. is the event listener firing (check with console or alert)
  2. can you scroll the page manually? in my case, if I open my code in Chrome (on computer), there is a scrollbar now and I can scroll down (but the aframe isn't moving). If not you might need to check the css overflow on your page.

I am testing with iPhone6SE btw. If this won't helpI will upload my example and send you the link to test if my code works for you.

(2. reminds me that this whole workaround should only be applied after a check if Safari is used to avoid unnecesary scrollbars)

jeroenVerdonschot commented 7 years ago

@derhuebiii

thanks for your time. Now it works but when I move from vr to pano and back the a-scene is a bit smaller resulting in a white line on the bottom or on the right (depending on landscape or portrait of course)

The strange part is that when I place a bookmark of the scene on my IPhone start screen is works perfect.

I'll keep on testing :(. Thanks

derhuebiii commented 7 years ago

@rambambulli Yes it is not a final perfect solution, more a quick hack. But it is something to work with and maybe build a solution.

For the start screen I heard that if you do this, iPhone allows "real" fullscreen. So this "hack" should even also only be activated in browser mode.

Maybe the aframe team can help on how to go on from here? As it is working in WebVR polyfill this sounds like an aframe topic for me, anyone from the team can point to someone who can have a look at this? Happy to support but this whole topic about identifying device and fullscreen seems a bit complex.

cvan commented 7 years ago

Thanks for looking into this. A-Frame already injects these <meta> tags for Safari/WebKit for iOS.

If you load your phone in landscape mode, the "pseudo-fullscreen mode" won't trigger. But, if you turn your phone back to portrait mode and then back to landscape mode, the "pseduo-fullscreen mode" will trigger. I looked in the webvr-polyfill, but I don't think it's caused by something there.

I've done a lot of researched, asked a lot of people, and – as far as I can tell – it's just how iOS behaviour works (unless you're in a pinned ). I've looked for a lot of workarounds (this week I checked and spent quite some time too).

Is this behaviour above what I'm describing, the same thing you're experiencing, @rambambulli @derhuebiii?

Videos, screencasts, images would help too - just to make sure we're seeing the same issues. Thanks for your help!

derhuebiii commented 7 years ago

If you load your phone in landscape mode, the "pseudo-fullscreen mode" won't trigger. But, if you turn your phone back to portrait mode and then back to landscape mode, the "pseduo-fullscreen mode" will trigger.

Yes, that's correct, didn't realize that before. If this workaround would be implemented a "pop-up"/modal like we get when entering the VR mode in portrait mode that a turn to portrait and back helps would also help for that problem. Of course not optimal, but the best we might get currently with iOS...

It is the same for the WebVR samples I referred to above, another hint for iOS behaviour.

cvan commented 7 years ago

Yes, that's correct, didn't realize that before. If this workaround would be implemented a "pop-up"/modal like we get when entering the VR mode in portrait mode that a turn to portrait and back helps would also help for that problem. Of course not optimal, but the best we might get currently with iOS...

Though not ideal, this is a good idea - thanks for the suggestion. (FYI, we also have #1239, which is somewhat related.) I'll repurpose this issue to address that. I'll grab this one; if you want to contribute a PR too, I can help review it. (Don't feel blocked on me, if you need this fixed, is what I'm saying.) Thanks for your help again 👍