WEB AR (二)

229 阅读2分钟

参考AR.js 结合vue three.js 实现基于位置的一个模型加载AR
本次demo运用的three.js 的版本为0.126.1

主要思路

  • 获取手机的媒体视频流
  • 将视频流作为场景的背景
  • 运用透视相机结合手机定位定位相机位置
  • 运用three.js 的设备控制器控制相机的移动

实现

获取手机媒体视频

getVideo() {function getUserMedia(constraints, success, error) {        if (navigator.mediaDevices.getUserMedia) {          //最新的标准API          navigator.mediaDevices            .getUserMedia(constraints)            .then(success)            .catch(error);        } else if (navigator.webkitGetUserMedia) {          //webkit核心浏览器          navigator.webkitGetUserMedia(constraints, success, error);        } else if (navigator.mozGetUserMedia) {          //firfox浏览器          navigator.mozGetUserMedia(constraints, success, error);        } else if (navigator.getUserMedia) {          //旧版API          navigator.getUserMedia(constraints, success, error);        }      }
function success(stream) {        //兼容webkit核心浏览器        // let CompatibleURL = window.URL || window.webkitURL;        //将视频流设置为video元素的源        console.log(stream);        //video.src = CompatibleURL.createObjectURL(stream);        video.srcObject = stream;        video.play();      }      function error(error) {        console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);      }      if (        navigator.mediaDevices.getUserMedia ||        navigator.getUserMedia ||        navigator.webkitGetUserMedia ||        navigator.mozGetUserMedia      ) {        //调用用户媒体设备, 访问摄像头        getUserMedia(          {            video: {              // width: window.innerWidth,              // height: window.innerHeight,              facingMode: {                exact: "environment",              },            },          },          success,          error        );      } else {        alert("不支持访问用户媒体");      }      video.addEventListener(        "pause",        function () {          window.clearInterval();        },        false      );      video.addEventListener(        "ended",        function () {          clearInterval();        },        false      );      return video;}

加载场景

init(){
      let _this = this;      let dom = document.getElementById("ARShow");      let width = dom.clientWidth;      let height = dom.clientHeight;      camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 100);       scene = new THREE.Scene(); // 创建场景
       // 将获取的视频流作为场景背景
      scene.background = new THREE.VideoTexture(_this.getVideo()); /      scene.updateMatrixWorld(true);      renderer = new THREE.WebGLRenderer({        alpha: true,      });      renderer.setSize(width, height);      dom.appendChild(renderer.domElement);       let material = new THREE.MeshBasicMaterial({          color: 0xff0000,        });      let pointLoaction = lglt2xyz(longitude, latitude); // 自定义的经纬度        let pointLoactionS = new THREE.Vector3(          pointLoaction.x,          0,          pointLoaction.z        );
     let pointGeometry = new THREE.CylinderGeometry(          0.3,          0.3,          2,          32        );        let pointMesh = new THREE.Mesh(pointGeometry, material);        pointMesh.position.set(          pointLoactionS.x,          pointLoactionS.y,          pointLoactionS.z        );         scene.add(pointMesh); // 网格模型添加到场景中
      controls = new DeviceOrientationControls(camera);
       function animate() {        window.requestAnimationFrame(animate);        camera.lookAt(scene.position);        camera.updateProjectionMatrix();        controls.update();        renderer.render(scene, camera);      }      animate();

}

将经纬度转换为世界坐标

function lglt2xyz(longitude, latitude, radius=6378137) {        var lg = THREE.Math.degToRad(longitude);        var lt = THREE.Math.degToRad(latitude);        var temp = radius * Math.cos(lt);        var x = temp * Math.sin(lg);        var y = radius * Math.sin(lt);        var z = temp * Math.cos(lg);        return {            x: x,            y: y,            z: z,        }    }

获取用户位置信息

 var timer = navigator.geolocation.watchPosition(        function (position) {          // watchPosition                    var longitude = position.coords.longitude;          var latitude = position.coords.latitude;          console.log("经度", longitude);          console.log("纬度", latitude);          let cameraPosition = lglt2xyz(longitude, latitude);          let cameraP = new THREE.Vector3(            cameraPosition.x,            3,            cameraPosition.z          );          camera.position.set(cameraP.x, cameraP.y, cameraP.z);          //   camera.target = new THREE.Vector3(          //     cameraPosition.x,          //     cameraPosition.y,          //     cameraPosition.z          //   );        },        function (error) {          alert(error.code);          //清除多次地理位置定位          navigator.geolocation.clearWatch(timer);        },        {          /*数据收集 :  json的形式             enableHighAcuracy  :  更精确的查找,默认false             timeout  :指定获取地理位置的超时时间,默认不限时,单位为毫秒             maximumAge :最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。             */          enableHighAccuracy: true,          maximumAge: 2,        }      );

手机定位有偏差效果可能会有偏差