JürgenB: deviceorientation-Event beenden

Hallo,

ich beschäftige mich gerade mit dem deviceorientation-Event.

In der mdn-Doku steht

This event is not cancelable and does not bubble.

und meine Tests unter IOS haben gezeigt, dass removeEventListener keine Wirkung zeigt. Gibt es keine Möglichkeit, das event „irgendwie“ zu beenden?

Gruß
Jürgen

  1. Hallo JürgenB,

    man muss den Eventlistener mit exakt dem gleichen Funktionsobjekt entfernen, womit man ihn angelegt hat. Nicht nur mit gleichen Funktion, sondern mit dem gleichen Objekt.

    Das ist - je nach Codeumgebung - nicht ganz so einfach. Beispiel für einen Fallstrick:

    function handleOrientation(activate) {
       if (activate)
          window.addEventListener("deviceorientation", orientationHandler);
       else
          window.removeEventListener("deviceorientation", orientationHandler);
    
       function orientationHandler(orientationEvent) {
          ...
       }
    }
    
    handleOrientation(true);
    handleOrientation(false);
    

    Die Deregistrierung wird hier nicht funktionieren, weil die orientationHandler-Funktion lokal in der handleOrientation-Funktion ist und deshalb bei jedem Aufruf von handleOrientation ein neues Funktionsobjekt vorliegt. Falls dein Eventhandler eine inline-Funktion oder eine Pfeilfunktion ist, bist Du sowieso chancenlos, weil dann die registrierte Handlerfunktion nur für den Moment der Registrierung in deinem Codebereich verfügbar ist.

    Wenn Du an window.ondeviceorientation verwendest, wäre es übrigens einfacher, weil - so würde ich behaupten - Du dann einfach ondeviceorientation auf undefined setzen kannst

    Cancelling und Bubbling haben mit einer Deregistrierung übrigens nichts zu tun, aber ich denke, das weißt Du.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      danke für die Tipps,

      man muss den Eventlistener mit exakt dem gleichen Funktionsobjekt entfernen, womit man ihn angelegt hat. Nicht nur mit gleichen Funktion, sondern mit dem gleichen Objekt.

      Das ist - je nach Codeumgebung - nicht ganz so einfach.

      da habe ich drauf geachtet. Der Handler ist eine globale Funktion.

      Wenn Du an window.ondeviceorientation verwendest, wäre es übrigens einfacher, weil - so würde ich behaupten - Du dann einfach ondeviceorientation auf undefined setzen kannst

      Das habe ich auch ausprobiert, ohne Erfolg.

      Cancelling und Bubbling haben mit einer Deregistrierung übrigens nichts zu tun, aber ich denke, das weißt Du.

      Im Prinzip ja, aber das war mein Strohhalm.

      Im Moment steckt mein Versuch in einem 1000-Zeilen-Script. Ich werde mal eine Testseite basteln, in der nur die Richtungsabfrage steckt und melde mich dann wieder.

      Gruß
      Jürgen

      1. Hallo,

        hier der Link zur Testseite: https://test.berkemeier.eu/Test/Kompass.html

        Ich habe bisher nur unter IOS getestet.

        Gruß
        Jürgen

        1. Hallo Jürgen,

          muss ich mir in Ruhe angucken, auf meinem Androiden passiert bei Knopfdruck scheinbar gar nichts. Möglicherweise, weil das Zertifikat ungültig ist, deviceorientation setzt einen sicheren Kontext voraus.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            ich habe es auch mal hier abgelegt, da ist das Zertifikat OK
            https://www.j-berkemeier.de/Kompass.html

            Auf dem iPhone kommt eine Abfrage, ob der Zugriff auf den Bewegungssensor OK ist. Wie das unter Android aussieht, weiß ich nicht. Ich habe evtl. am Sa Zugriff auf ein altes Samsung. Aber mehr als „gucken ob's geht“ kann ich da nicht.

            Aber vielleicht siehst du oder jemand anderes ja einen Fehler in meinem Code.

            Meine Quelle: https://stackoverflow.com/questions/2564219/accessing-iphone-compass-with-javascript bzw. https://dev.to/orkhanjafarovr/real-compass-on-mobile-browsers-with-javascript-3emi

            Gruß
            Jürgen

            1. Hallo Jürgen,

              immer noch nichts, das muss ich debuggen 🤷‍♂️. Habe aber mein USB Kabel nicht hier…

              Rolf

              --
              sumpsi - posui - obstruxi
              1. Hallo,

                welche technischen Voraussetzungen muss das Gerät denn erfüllen? Kann man die abfragen?

                Gruß
                Kalk

                1. Hallo Tabellenkalk,

                  das DeviceOrientationEvent muss da sein, und unter iOS gibt's auch die requestPermission Methode darauf.

                  Ob das Gerät einen Kompass besitzt, ist eine andere Frage. Technische Fähigkeiten abfragen ist immer auch eine Möglichkeit zum Fingerprinting und deshalb nicht so einfach. Spontan finde ich keine Testmöglichkeit, ob ein Kompass/Magnetsensor vorhanden ist oder nicht.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
            2. Hallo Jürgen,

              if (isIOS) {
                 window.ondeviceorientation = compasHandler;
                 console.log("I-Kompass an!");
              } else {
                 window.deviceorientationabsolute = compasHandler;
                 console.log("A-Kompass an!");
              }
              

              (1) Warum absolute unter Android, aber nicht iOS? Funktioniert unter iOS nur der relative Kompass? (2) Warum ein on... unter iOS, aber nicht unter Android? (3) Eine HTML-Indikation, ob der Kompass an oder aus ist, wäre hilfreich. Auf dem Handy sieht man console.log nicht. (4) Statt den Navigator zu bitten, zwischen Äpfeln und Birnen zu unterscheiden, würde ich Dir empfehlen, auf die Existenz der requestPermission-Methode zu testen. Die Frage, nach welchen Regeln Du zwischen absolutem und relativem Kompass unterscheiden musst, beantwortet das nicht, aber erstmal wäre ja die Frage zu stellen, ob Du das überhaupt musst.

              async function registerOrientationHandler(orientationHandler) {
                 if (DeviceOrientationEvent.requestPermission) {
                    if ("granted" != await DeviceOrientationEvent.requestPermission()) {
                       console.log("Orientation-Handler wurde abgelehnt");
                       return false;
                    }
                 }
                 window.ondeviceorientation = orientationHandler;
                 console.log("Orientation-Handler wurde registriert");
                 return true;
              }
              
              registerOrientationHandler(compasHandler);
              

              Edit: Fehlende {} ergänzt, danke Felix!

              Das kann man auch anders bauen, z.B. geht in einem type="module" Script auch ein top-level await, aber so ist die Registrierung und die Erlaubnisanfrage schön gekapselt. Und normalerweise muss man ja auch nicht auf die Erfolgsmeldung warten.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. Hallo Rolf,

                das mit dem fehlendem on war der entscheidende Tipp. Ich habe das auch beim Entfernen der Eventhandler korrigiert. Da war ich gestern Abend einfach betriebsblind. Jetzt lässt sich der Eventhandler unter IOS auch entfernen.

                Es gibt zwei Events: deviceorientation und deviceorientationabsolute. Das erste wird von IOS und Android unter stützt, kann aber nur die relative Ausrichtung abfragen. Aber dafür gibt es für die i-Geräte noch webkitCompassHeading. deviceorientationabsolute witd nur von den a-Geräten unterstützt. Die Abfrage in der jetzigen Form habe ich bei der weiter oben angegebenen Quelle abgeschrieben. Möglicherweise wäre es besser, auf deviceorientationabsolute abzufragen, und wenn nicht unterstützt, deviceorientation mit webkitCompassHeading zu nehmen. Aber so weit bin ich noch nicht.

                Aber schon mal vielen Dank für die Hilfe. Super wäre, wenn du auch die jetzige Version (mit on) unter Android testen könntest.

                Gruß
                Jürgen

                1. Hallo Jürgen,

                  jetzt zeigt er was an. Aber was er anzeigt, ist ziemlich erratisch und hängt vermutlich primär von der Stahlverteilung um das Handy herum ab. Mit Norden hat das wenig zu tun. Ich muss das wohl mal bei einem Waldspaziergang testen - allerdings hat meine Handyhülle einen Magnetverschluss, so dass es auch da zu Problemen kommen wird.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. Hallo Rolf,

                    jetzt zeigt er was an.

                    lässt sich der Eventhandler denn auch entfernen?

                    Gruß
                    Jürgen

                    1. Hallo Jürgen,

                      wenn ich "Kompass aus" tippe, aktualisieren die Zahlen nicht mehr.

                      Weiter gehende Aussagen mache ich nur mit meinem Alltours.

                      Rolf

                      --
                      sumpsi - posui - obstruxi
                      1. Hallo Rolf,

                        danke, dann scheint das bis auf die Wette bei dir auch zu funktionieren.

                        Gruß
                        Jürgen

              2. Lieber Rolf,

                sehe ich da ein fehlendes geschweiftes Klammernpaar?

                   if (DeviceOrientationEvent.requestPermission) {
                      if ("granted" != await DeviceOrientationEvent.requestPermission())
                         console.log("Orientation-Handler wurde abgelehnt");
                         return false;
                   }
                

                Das return false wird immer ausgeführt. Der Einrückung nach ist das wahrscheinlich nicht gewollt.

                Liebe Grüße

                Felix Riesterer

                1. Hallo Felix,

                  sehr gut, Test bestanden 😉

                  Sowas passiert, wenn man Code trocken schreibt ohne ihn zu testen…

                  Rolf

                  --
                  sumpsi - posui - obstruxi
  2. Dieser Beitrag wurde gelöscht: Beitrag ist Spam.
  3. Hallo,

    ich habe meinen Test jetzt noch einmal überarbeitet:

    https://www.j-berkemeier.de/Kompass_V2.html

    Man kann sich jetzt den Quelltext auch ohne Console ansehen. Es wäre schön, wenn jemand mit Android-Gerät die Seite testen könnte.

    Mein Stand zum Entfernen des deviceorientation(absolute)-Handlers:

    ondeviceorientation = handler;
    ....
    ondeviceorientation = null; //undefined;
    

    funktioniert.

    addEventListener notiert zwar den Handler, removeEventListener entfernt ihn aber nicht.

    Mit controller.abort() kann der Handler zwar entfernt werden, aber, wie zu erwarten, final.

    Gruß
    Jürgen

    1. Lieber JürgenB,

      https://www.j-berkemeier.de/Kompass_V2.html

      [...]Es wäre schön, wenn jemand mit Android-Gerät die Seite testen könnte.

      meine Ausgabe:

      Heading: degree
      
      Log: DeviceOrientationEvent: function
      DeviceOrientationEvent.requestPermission: undefined
      DeviceOrientationEvent.deviceorientation: undefined
      DeviceOrientationEvent.deviceorientationabsolute: undefined
      window.ondeviceorientation: object
      window.ondeviceorientationabsolute: object
      deviceorientation: true
      deviceorientationabsolute: true
      A-Kompass an!
      Kompass aus!
      A-Kompass an!
      Kompass aus!
      

      Liebe Grüße

      Felix Riesterer

      1. Hallo Felix,

        vielen Dank. Wurde bei „A-Kompass an“ auch die Richtung angezeigt? Also eine Zahl zwischen 0 und 360 zwischen Heading: und Degree?

        Gruß
        Jürgen

        1. Hallo JürgenB,

          bei mir ja.

          Aber das hier:

          DeviceOrientationEvent.deviceorientation: undefined DeviceOrientationEvent.deviceorientationabsolute: undefined

          ist ein Fehler - das sind keine statischen Properties, sondern Properties eines Eventobjekts.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            das sind die erfolglosen Versuche, den Eventsupport zu prüfen, um auf Browsersniffing zu verzichten. Ich mache das jetzt mit

            const supportsDeviceorientation = ("ondeviceorientation" in window);
            

            Gruß
            Jürgen