3D模型工具栏-AR效果

简介: 3D模型工具栏-AR效果

工具栏-AR效果代码展示:

 

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <title>工具栏-AR效果</title>
    <script src="./js/three.js"></script>
    <script src="./js/OBJLoader.js"></script>
    <script src="./js/OrbitControls.js"></script>
    <style>
      /* 初始化页面 */
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      /* 设置渲染容器的大小 */
      #webgl {
        width: 100%;
        height: 100vh;
        overflow: hidden;
      }
      /* 设置最大元素宽高 */
      .content{
        width: 100%;
        height: 100vh;
        position: relative;
      }
      /* 将工具栏定位到页面右下角 */
      .tool{
        position: absolute;
        bottom: 0;
        right: 0;
        margin-right: 20px;
        display: flex;
        user-select: none;
      }
      /* 设置每一个块的大小 */
      .tool-item{
        width: 35px;
        height: 35px;
        padding: 5px;
        position: relative;
      }
      /* 设置小图标黑色背景 */
      .tool-img{
        display: flex;
        justify-content: center;
        align-items: center;
        width: 25px;
        height: 25px;
        border-radius: 100%;
        background-color: rgba(0,0,0,0.8);
      }
      /* 设置小图标大小 */
      .tool-img img{
        width: 13px;
        height: 13px;
      }
      /* 设置小图标的提示文本 */
      .tool-text{
        display: block;
        line-height: 20px;
        padding: 6px 0px;
        border-radius: 5px;
        background-color: #000000;
        font-size: 12px;
        text-align: center;
        color: #FFFFFF;
        position: absolute;
        bottom: 40px;
        left: 50%;
        display: none;
      }
      /* 设置提示文本下边的小三角 */
      .tool-item i{
        display: none;
        width: 10px;
        height: 10px;
        background-color: #000000;
        position: absolute;
        bottom: 36px;
        left: 50%;
        margin-left: -5px;
        transform: rotate(45deg);
      }
      /* 鼠标放到每一块上显示提示文本 */
      .tool-item:hover .tool-text{
        display: block;
      }
      /* 鼠标放到每一块上显示小三角 */
      .tool-item:hover i{
        display: block;
      }
      /* 设置查看弹窗大小和位置 */
      .popout{
        width: 160px;
        position: absolute;
        bottom: 40px;
        background-color: #000000;
        padding: 6px 0;
        border-radius: 10px;
        font-size: 12px;
        color: #FFFFFF;
        right: -30px;
        z-index: 100;
      }
      /* 设置查看弹窗下边的小三角 */
      .popout-arrow{
        display: block;
        width: 10px;
        height: 10px;
        background-color: #000000;
        position: absolute;
        bottom: 36px;
        left: 50%;
        margin-left: -5px;
        transform: rotate(45deg);
      }
      /* 设置弹窗中每行的大小 */
      .popout p{
        width: 90%;
        height: 30px;
        margin-left: 5%;
        display: flex;
        justify-content: space-between;
        line-height: 30px;
      }
      /* 设置弹窗中每行箭头的大小 */
      .popout>p img{
        width: 12px;
        height: 12px;
        margin: 9px 0px;
      }
      /* 设置弹窗中的分界线 */
      .popout em{
        display: block;
        width: 100%;
        height: 1px;
        background-color: #525252;
      }
      /* 设置弹窗中背景图的那一行 */
      .popout-list{
        width: 90%;
        height: 30px;
        margin-left: 5%;
        padding: 5px 0;
        display: flex;
      }
      /* 设置背景图中左右按钮的大小 */
      .popout-list>img{
        width: 14px;
        height: 14px;
        margin: 3px;
      }
      /* 设置背景图列表 */
      .popout-pic{
        display: flex;
        justify-content: space-between;
        width: calc(100% - 40px);
      }
      /* 设置背景图大小 */
      .popout-pic img{
        width: 20px;
        height: 20px;
      }
    </style>
  </head>
  <body>
    <div class="content">
      <!-- 渲染容器 -->
      <div id="webgl"></div>
      <!-- 工具栏 -->
      <div class="tool">
        <div class="tool-item">
          <span class="tool-text" id="rotate-text" style="width: 70px;margin-left: -35px;">开启旋转</span>
          <i></i>
          <div class="tool-img" onclick="rotates()">
            <img src="./img/旋转.png" alt="">
          </div>
        </div>
        <div class="tool-item">
          <span class="tool-text" id="AR-text" style="width: 70px;margin-left: -35px;">开启AR</span>
          <i></i>
          <div class="tool-img" onclick="ARs()">
            <img src="./img/AR.png" alt="">
          </div>
        </div>
        <div class="tool-item">
          <span class="tool-text" style="width: 50px;margin-left: -25px;">帮助</span>
          <i></i>
          <div class="tool-img">
            <img src="./img/帮助.png" alt="">
          </div>
        </div>
        <div class="tool-item">
          <span class="tool-text" style="width: 70px;margin-left: -35px;">查看方式</span>
          <i></i>
          <div onclick="look()" class="tool-img">
            <img src="./img/查看.png" alt="">
          </div>
          <!-- 查看弹窗 -->
          <div class="popout" style="display: none;">
            <p onclick="unfold(event)"><span>展示模式</span><img src="img/展开.png" alt=""></p>
            <p style="padding-left: 10px;display: none;"><span>允许缩放</span><img src="./img/对.png" alt=""></p>
            <em></em>
            <p onclick="unfold(event)"><span>背景切换</span><img src="./img/展开.png" alt=""></p>
            <div class="popout-list" style="display: none;">
              <img onclick="picLeft()" src="./img/左箭头.png" alt="">
              <div class="popout-pic">
                <img src="./img/pic1.jpg" >
                <img src="./img/pic2.webp" >
                <img src="./img/pic3.webp" >
                <img src="./img/pic4.webp" >
              </div>
              <img onclick="picRight()" src="./img/右箭头.png" alt="">
            </div>
          </div>
          <b class="popout-arrow" style="display: none;"></b>
        </div>
        <div class="tool-item">
          <span class="tool-text" style="width: 70px;margin-left: -35px;">开启VR</span>
          <i></i>
          <div class="tool-img">
            <img src="./img/VR.png" alt="">
          </div>
        </div>
        <div class="tool-item">
          <span class="tool-text" style="width: 70px;margin-left: -35px;">开启全屏</span>
          <i></i>
          <div class="tool-img">
            <img src="./img/全屏.png" alt="">
          </div>
        </div>
      </div>
    </div>
    <script>
      // 获取渲染容器
      let webgl = document.getElementById("webgl");
      // 获取渲染容器的宽高
      let webglWidth = webgl.offsetWidth;
      let webglHeight = webgl.offsetHeight;
      // 创建场景
      let scene = new THREE.Scene();
      // 设置环境光(十六进制颜色)
      let ambient = new THREE.AmbientLight(0x444444);
      // 将环境光添加到场景中
      scene.add(ambient);
      // 设置点光源(十六进制颜色)
      let point = new THREE.PointLight(0xffffff);
      // 设置点光源的位置(x轴, y轴, z轴)
      point.position.set(400, 200, 300); 
      // 将点光源添加到场景中
      scene.add(point);
      // 创建透视相机(角度, 宽高比, 最近距离, 最远距离)
      let camera = new THREE.PerspectiveCamera(60,webglWidth/webglHeight,0.1,2000);
      // 设置相机的位置(x轴, y轴, z轴)
      camera.position.set(100, 100, 100); 
      // 将相机指向场景中心
      camera.lookAt(scene.position);
      // 创建渲染器
      let renderer = new THREE.WebGLRenderer();
      // 设置渲染器的初始颜色(十六进制颜色, 透明度)
      renderer.setClearColor(0xEEEEEE,1);
      // 设置渲染器大小(标签宽度, 标签高度)
      renderer.setSize(webglWidth,webglHeight);
      // 将渲染器添加到渲染容器中(渲染器元素)
      webgl.appendChild(renderer.domElement);
      // 创建旋转状态
      let rotateStatus = false;
      // 创建渲染函数
      function render(){
        // 渲染场景和相机(场景, 相机)
        renderer.render(scene,camera);
        // 判断旋转状态为 ture 则执行
        if(rotateStatus){
          // 设置场景旋转速度
          scene.rotation.y += 0.002;
        }
        // 重复执行渲染函数
        requestAnimationFrame(render);
      }
      // 调用渲染函数
      render();
      // 设置窗口变化自适应调整事件
      window.onresize = function(){
        // 重新获取渲染容器的宽高
        webglWidth = webgl.offsetWidth;
        webglHeight = webgl.offsetHeight;
        // 重置渲染器canvas画布大小
        renderer.setSize(webglWidth,webglHeight);
        // 重置相机显示范围的宽高比
        camera.aspect = webglWidth/webglHeight;
        // 更新相机的投影矩阵
        camera.updateProjectionMatrix();
        // 重新调用渲染函数
        render();
      };
      // 创建 OBJ 模型加载器
      let loader = new THREE.OBJLoader();
      // 加载 OBJ 文件
      loader.load('./img/鹤.OBJ', function(obj) {
        // 加载纹理贴图
        let texture = new THREE.TextureLoader().load('./img/he.png',function(){
          render(); // 加载成功后重新调用渲染函数
        });
        // 给 OBJ 模型设置纹理贴图
        obj.children[0].material = new THREE.MeshBasicMaterial({ map: texture });
        // 将 OBJ 模型添加到场景中
        scene.add(obj);
        // 设置 OBJ 模型居中
        obj.children[0].geometry.center();
        // 设置 OBJ 模型缩放大小
        obj.children[0].scale.set(100, 100, 100);
      })
      // 鼠标操作三维场景
      let controls = new THREE.OrbitControls(camera,renderer.domElement);
      // 查看弹窗显示隐藏事件
      function look(){
        // 获取查看弹窗
        let popout = document.getElementsByClassName("popout")[0];
        // 获取查看弹窗下边的小三角
        let arrow = document.getElementsByClassName("popout-arrow")[0];
        // 判断弹窗是否隐藏
        if(popout.style.display == "none"){
          // 如果隐藏,显示弹窗和小三角
          popout.style.display = "block";
          arrow.style.display = "block";
        }else{
          // 如果显示,则隐藏弹窗和小三角
          popout.style.display = "none";
          arrow.style.display = "none";
        }
      }
      // 查看弹窗功能展开事件
      function unfold(e){
        // 获取事件目标对象
        e = e || window.event;
        let targets = e.target || e.srcElement;
        // 创建变量用于存储下一个同级元素
        let nexts;
        // 创建变量用于存储当前 p 标签内的 img 标签
        let pImg;
        // 当前目标元素是否为 p 标签
        if(targets.nodeName == "P"){
          // 如果为p标签,存储当前目标元素的下一个同级元素
          nexts = targets.nextElementSibling;
          // 存储当前 p 标签内的 img 标签
          pImg = targets.getElementsByTagName("img")[0];
        }else{
          // 如果不是p标签,存储当前目标元素的父元素的下一个同级元素
          nexts = targets.parentElement.nextElementSibling;
          // 存储当前目标元素的父元素内的 img 标签
          pImg = targets.parentElement.getElementsByTagName("img")[0];
        }
        // 判断下一个同级元素是否隐藏
        if(nexts.style.display == "none"){
          // 如果隐藏则显示
          nexts.style.display = "flex";
          // 设置小图标箭头朝下
          pImg.style.transform = "rotate(90deg)";
        }else{
          // 如果显示则隐藏
          nexts.style.display = "none";
          // 设置小图标箭头朝右
          pImg.style.transform = "rotate(0deg)";
        }
      }
      // 模拟背景图片数据
      let arr = [
        "./img/pic1.jpg",
        "./img/pic2.webp",
        "./img/pic3.webp",
        "./img/pic4.webp",
        "./img/pic5.jpg"
      ];
      // 输出背景图数据
      // 创建起始值,表示从第几张图片开始输出
      let begin = 0;
      // 创建结束值,表示到第几张图片输出结束
      // 并且判断图片数量是否大于等于4,如果大于设置为 4,否则设置为图片的数量
      let record = arr.length >= 4 ? 4 : arr.length;
      // 创建背景图渲染函数
      function picRender(){
        // 创建变量,存储拼接的字符串
        let picStr = "";
        // 循环拼接数据,从 begin 开始,到 record 结束
        for(let i = begin; i < record; i++){
          picStr += `<img src="${arr[i]}" >`;
        }
        // 向页面输出数据
        document.getElementsByClassName("popout-pic")[0].innerHTML = picStr;
      }
      // 调用背景图渲染函数
      picRender();
      // 背景图切换-左按钮事件
      function picLeft(){
        // 判断起始值是否大于 0
        if(begin > 0){
          // 如果大于 0 让 起始值 和 结束值 都减一
          record--;
          begin--;
          // 重新调用背景图渲染函数
          picRender();
        }
      }
      // 背景图切换-右按钮事件
      function picRight(){
        // 判断图片数量减起始值是否大于 4
        if(arr.length - begin > 4){
          // 如果大于 4 让 起始值 和 结束值 都加一
          record++;
          begin++;
          // 重新调用背景图渲染函数
          picRender();
        }
      }
      // 创建模型旋转点击事件
      function rotates(){
        // 获取旋转提问文本
        let rotateText = document.getElementById("rotate-text");
        // 取反旋转状态
        rotateStatus = !rotateStatus;
        // 判断旋转状态是否为 true
        if(rotateStatus){
          // 如果为 true,设置提示文本为停止旋转
          rotateText.innerHTML = "停止旋转";
        }else{
          // 如果为 false,设置提示文本为开启旋转
          rotateText.innerHTML = "开启旋转";
        }
      }
      // 创建 AR 状态
      let ARStatus = false;
      // 创建 AR 开关事件
      function ARs(){
        // 获取 AR 提示文本
        let ARText = document.getElementById("AR-text");
        // 取反 AR 状态
        ARStatus = !ARStatus;
        // 判断 AR 状态是否为 true
        if(ARStatus){
          // 如果为 true 设置渲染器背景色为黑色
          renderer.setClearColor(0x000000,1);
          // 设置提示文本为关闭AR
          ARText.innerHTML = "关闭AR";
        }else{
          // 否则设置渲染器背景色为灰色
          renderer.setClearColor(0xEEEEEE,1);
          // 设置提示文本为开启AR
          ARText.innerHTML = "开启AR";
        }
      }
    </script>
  </body>
</html>

工具栏-AR展示效果:

原创作者:吴小糖

创作时间:2022.11.6

相关文章
|
6月前
|
机器学习/深度学习 程序员 数据处理
时间序列分析技巧(一):根据ACF、PACF进行AR、MA、ARMA模型选择
时间序列分析技巧(一):根据ACF、PACF进行AR、MA、ARMA模型选择
|
3月前
|
机器学习/深度学习 vr&ar
Sora视频重建与创新路线问题之Perceiver AR模型模态无关的自回归生成如何处理
Sora视频重建与创新路线问题之Perceiver AR模型模态无关的自回归生成如何处理
|
6月前
|
存储 vr&ar
R语言用AR,MA,ARIMA 模型进行时间序列预测
R语言用AR,MA,ARIMA 模型进行时间序列预测
|
6月前
|
资源调度 监控 数据挖掘
R语言使用多元AR-GARCH模型衡量市场风险
R语言使用多元AR-GARCH模型衡量市场风险
|
6月前
|
vr&ar 开发工具 图形学
【Unity 3D】使用EasyAR实现单图识别的AR增强现实功能(附实现步骤)
【Unity 3D】使用EasyAR实现单图识别的AR增强现实功能(附实现步骤)
274 0
|
机器学习/深度学习 算法 Go
本周推荐 | 电商3D购物新体验:AR量脚和AR试戴背后的算法技术
推荐语:本文结合了工业实际应用,介绍了工程上精心设计量脚交互流程,算法上融合2d检测、3d重建来实现较为精准的量脚流程,并在一系列算法流程计算上,充分考虑到了算法效率,保证了用户体验,具有很实用的价值。 ——大淘宝技术算法工程师 尘漠
422 0
本周推荐 | 电商3D购物新体验:AR量脚和AR试戴背后的算法技术
|
机器学习/深度学习 自动驾驶 算法
2020云栖大会智慧出行专场:聚焦高精地图/算法、智能模型、自动驾驶、AR导航
大量前沿、创新性技术目前已经广泛应用于高德地图各项产品中,本论坛将着重讲述「高精地图、高精算法、智能时空预测模型、自动驾驶、AR导航、车道级技术」等话题,全面解析最新技术进展和场景化的实践经验,并与开发者们一起交流、讨论
2020云栖大会智慧出行专场:聚焦高精地图/算法、智能模型、自动驾驶、AR导航