【问题标题】:How do I get DeviceOrientationEvent and DeviceMotionEvent to work on Safari?如何让 DeviceOrientationEvent 和 DeviceMotionEvent 在 Safari 上工作?
【发布时间】:2019-10-24 03:06:39
【问题描述】:

我正在尝试在我的网站上实现 DeviceOrientationEvent 和 DeviceMotionEvent 以获得 3D 效果。但是,控制台不记录任何信息,显然 iOS 13 需要用户设置权限才能开始执行此操作。我似乎无法弄清楚如何正确设置它。

我做了一些研究,这就是我发现的:https://github.com/w3c/deviceorientation/issues/57#issuecomment-498417027

遗憾的是,网上提供的所有其他方法都不再可用了。

window.addEventListener('deviceorientation', function(event) {
    console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma);
});

我收到以下错误消息:

[警告] 在请求并授予权限之前,不会触发任何设备运动或方向事件。

【问题讨论】:

    标签: javascript safari mobile-safari device-orientation devicemotion


    【解决方案1】:

    从 iOS 13 beta 2 开始,您需要调用 DeviceOrientationEvent.requestPermission() 来访问陀螺仪或加速度计。这将显示一个权限对话框,提示用户允许此站点的运动和方向访问。

    请注意,如果您尝试在页面加载时自动调用它,这将不起作用。用户需要执行一些操作(例如点击按钮)才能显示对话框。

    此外,目前的实施似乎要求网站启用 https。

    欲了解更多信息,请参阅this page

    【讨论】:

      【解决方案2】:
      if ( location.protocol != "https:" ) {
      location.href = "https:" + window.location.href.substring( window.location.protocol.length );
      }
      function permission () {
          if ( typeof( DeviceMotionEvent ) !== "undefined" && typeof( DeviceMotionEvent.requestPermission ) === "function" ) {
              // (optional) Do something before API request prompt.
              DeviceMotionEvent.requestPermission()
                  .then( response => {
                  // (optional) Do something after API prompt dismissed.
                  if ( response == "granted" ) {
                      window.addEventListener( "devicemotion", (e) => {
                          // do something for 'e' here.
                      })
                  }
              })
                  .catch( console.error )
          } else {
              alert( "DeviceMotionEvent is not defined" );
          }
      }
      const btn = document.getElementById( "request" );
      btn.addEventListener( "click", permission );
      

      在您的页面上使用一个元素作为事件触发器,并给它一个“请求”的 id。

      这将在请求 API 授权之前检查 https 并根据需要进行更改。 昨天找到了,但不记得网址了。

      【讨论】:

      • 这会在我的 iPhone 6S (iOS 12) 上的 Safari 浏览器中提醒“DeviceMotionEvent 未定义”。为什么它不起作用?
      【解决方案3】:

      您需要单击或用户手势来调用 requestPermission()。 像这样:

      <script type="text/javascript">
          function requestOrientationPermission(){
              DeviceOrientationEvent.requestPermission()
              .then(response => {
                  if (response == 'granted') {
                      window.addEventListener('deviceorientation', (e) => {
                          // do something with e
                      })
                  }
              })
              .catch(console.error)
          }
      </script>
      
      <button onclick='requestOrientationPermission();'>Request orientation permission</button>
      

      注意:如果您在权限提示上单击取消并想再次对其进行测试,则需要退出 Safari 并重新启动它才能返回提示。

      【讨论】:

        【解决方案4】:

        在 Xamarin iOS (Xamarin.Forms) 上,您可以在 WkWebView 准备好时使用 EvaluateJavaScript 方法注入权限请求脚本:

        webView.EvaluateJavaScript("DeviceMotionEvent.requestPermission().then(response => { if (response == 'granted') {window.addEventListener('devicemotion', (e) => {})}}).catch(console.error)");
        

        如果使用自定义的 WkWebView 渲染器(如果这个 bug 还在 https://bugs.webkit.org/show_bug.cgi?id=203287 附近,则必须实现 IWKUIDelegate)在 OnElementChanged 中设置 webView 控件时可以注入脚本

        例子:

        // do this when setting up the webview control in OnElementChanged
                        //enable device motion sensors permission script:
                        //https://medium.com/flawless-app-stories/how-to-request-device-motion-and-orientation-permission-in-ios-13-74fc9d6cd140
                        var source =
                        "function requestSensorPermission() {" +
                        "   if (typeof(DeviceMotionEvent) !== 'undefined' && typeof(DeviceMotionEvent.requestPermission) === 'function') {" +
                        "       DeviceMotionEvent.requestPermission() .then(response => {" +
                        "           if (response == 'granted') { " +
                        "               window.addEventListener('devicemotion', (e) => { })" +
                        "           }" +
                        "       }).catch(console.error)" +
                        "   }" +
                        "}";
                        var script = new WKUserScript(new NSString(source), WKUserScriptInjectionTime.AtDocumentEnd, true);
                        wkWebView.Configuration.UserContentController.AddUserScript(script);
        

        然后,当 yourCustomWebView 准备就绪时,您可以在后面的代码中调用 yourCustomWebView.EvaluateJavaScript("requestSensorPermission()")。

        评估JavaScript: https://docs.microsoft.com/en-us/dotnet/api/webkit.wkwebview.evaluatejavascript?view=xamarin-ios-sdk-12

        自定义 WkWebView 渲染器: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview#create-the-custom-renderer-on-ios

        【讨论】:

          【解决方案5】:

          这并不是一个真正的答案,但如果在 WKWebView 上使用 DeviceMotion,则需要考虑一些问题。

          在 Xcode 13 上,您可以使用这个新的 WKUIDelegate。您仍然需要像其他答案提到的那样请求权限,但它不会提示用户提供权限,而是直接授予它。

          @available(iOS 15, *)
          func webView(_ webView: WKWebView,
              requestDeviceOrientationAndMotionPermissionFor origin: WKSecurityOrigin,
                   initiatedByFrame frame: WKFrameInfo,
                    decisionHandler: @escaping (WKPermissionDecision) -> Void) {
              decisionHandler(.grant)
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-06-05
            • 1970-01-01
            • 2018-12-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-06-18
            • 1970-01-01
            相关资源
            最近更新 更多