1. 程式人生 > 實用技巧 >javascript 陀螺儀加攝像頭可以玩出AR效果

javascript 陀螺儀加攝像頭可以玩出AR效果

原文連結:https://blog.jijian.link/2020-09-08/js-ar/

重要事情說三遍

此文章中的API介面,必須放在 https 協議下測試!瀏覽器APP必須開啟攝像頭許可權!此文章程式碼僅在 chrome 手機瀏覽器及微信中測試通過。

此處省略兩遍。

示例

本文僅使用陀螺儀模擬 AR 效果,完整 AR 逃不掉一整套演算法,本菜鳥還做不到啊。

DEMO 演示效果

程式碼如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content
="width=device-width, initial-scale=1.0"> <title>陀螺儀模擬AR效果</title> <style> #video { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 100%; height: 100vh; background-color: #141414; } #address { position
: fixed; left: 50%; top: 50%; width: 40px; height: 60px; border-radius: 100%; background-color: #009900; z-index: 4; color: #fff; } </style> </head> <body> <div id="address"></div> <video id="video" autoplay="autoplay"></
video> <script> var video = document.getElementById('video'); //預設使用前攝像頭,強制使用後置攝像頭如下設定 var constraints = {video: { facingMode: { exact: "environment" } }}; // let constraints = { video: true }; navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { // 舊的瀏覽器可能沒有srcObject window.stream = stream; if ("srcObject" in video) { video.srcObject = stream; } else { // 防止在新的瀏覽器裡使用它,應為它已經不再支援了 video.src = window.URL.createObjectURL(stream); } video.onloadedmetadata = function() { video.play(); }; }).catch(function(err) { console.error(err.name + ": " + err.message); }); // http://stackoverflow.com/questions/18112729/calculate-compass-heading-from-deviceorientation-event-api/21829819#21829819 // todo 演算法來源 https://my.oschina.net/u/2324376/blog/790939 function compassHeading(alpha, beta, gamma) { // Convert degrees to radians var alphaRad = alpha * (Math.PI / 180); var betaRad = beta * (Math.PI / 180); var gammaRad = gamma * (Math.PI / 180); // Calculate equation components var cA = Math.cos(alphaRad); var sA = Math.sin(alphaRad); // var cB = Math.cos(betaRad); var sB = Math.sin(betaRad); var cG = Math.cos(gammaRad); var sG = Math.sin(gammaRad); // Calculate A, B, C rotation components var rA = - cA * sG - sA * sB * cG; var rB = - sA * sG + cA * sB * cG; // var rC = - cB * cG; // Calculate compass heading var compassHeading = Math.atan(rA / rB); // Convert from half unit circle to whole unit circle if(rB < 0) { compassHeading += Math.PI; }else if(rA < 0) { compassHeading += 2 * Math.PI; } // Convert radians to degrees compassHeading *= 180 / Math.PI; return compassHeading; } function updateGravity (event) { const that = this; // !根據陀螺儀獲取旋轉角度,設定人物位置 const winWidth = document.documentElement.clientWidth; const itemWidth = parseInt(window.getComputedStyle(address).width); const heading = 360 - compassHeading(event.alpha, event.beta, event.gamma); const angle = 0; address.style.transform = 'rotate('+(heading - 90 + angle)+'deg)'; // `${(winWidth - itemWidth) * Math.min(180, Math.max(0, (heading + 360 - angle) % 360)) / 180}px` 移動區間 0 - 180 address.style.left = `${(winWidth - itemWidth) * ((heading + 360 - angle) % 360) / 180}px`; } window.addEventListener('deviceorientation', updateGravity, false); </script> </body> </html>