使用three.js和CSS3DRenderer.js构建3D空间图片

分为两个部分,html部分和js引入部分,自己感兴趣也可以去three.js官网看,都有源码

three.js gitHub库地址:https://github.com/mrdoob/three.js

three.js 官网 Three.js中文网

html部分:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>css3d</title>
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
    />
    <style>
      body {
        background-color: #000000;
        margin: 0;
        cursor: move;
        overflow: hidden;
      }
      a {
        color: #ffffff;
      }
      · #info {
        position: absolute;
        width: 100%;
        color: #ffffff;
        padding: 5px;
        font-family: Monospace;
        font-size: 13px;
        font-weight: bold;
        text-align: center;
        z-index: 1;
      }
    </style>
  </head>
  <body>
    <script src="./three.js"></script>
    <script src="./CSS3DRenderer.js"></script>
    <script>
      //定义相机,场景,渲染器,是3D场景形成的三大要素
      var camera, scene, renderer;
      //定义几何体,材质,以及几何体加材质之后形成的网格
      var geometry, material, mesh;
      //生成三维向量(0,0,0),相机的目标点
      var target = new THREE.Vector3();
      //lon 经度 竖着的 有东经 西经 ;lat 维度 横着的 有南纬 北纬
      //该经纬表示相机的聚焦点,初始状态在前面
      var lon = 90,
        lat = 0;
      //同样是相机的聚焦点,上面是角度,此处转化为弧度制
      var phi = 0,
        theta = 0;
      //移动端用户输入的x,y
      var touchX, touchY;

      init();
      animate();

      function init() {
        //相机的默认位置在坐标系的原点
        camera = new THREE.PerspectiveCamera(
          75,
          window.innerWidth / window.innerHeight,
          1,
          1000
        );
        //创建场景
        scene = new THREE.Scene();
        //右手坐标系,z朝向观察者,即相机。下面是将六个面拼接成立方体,分别对应
        //这里的图片可以krpano 或则 pano2vr工具生成6张图
        var sides = [
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //右侧 
            position: [-512, 0, 0],
            rotation: [0, Math.PI / 2, 0],
          },
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //左侧 
            position: [512, 0, 0],
            rotation: [0, -Math.PI / 2, 0],
          },
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //上侧 
            position: [0, 512, 0],
            rotation: [Math.PI / 2, 0, Math.PI],
          },
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //下侧 
            position: [0, -512, 0],
            rotation: [-Math.PI / 2, 0, Math.PI],
          },
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //前 
            position: [0, 0, 512],
            rotation: [0, Math.PI, 0],
          },
          {
            url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //后 
            position: [0, 0, -512],
            rotation: [0, 0, 0],
          },
        ];
        //将六个图片添加到场景中
        for (var i = 0; i < sides.length; i++) {
          var side = sides[i];
          var element = document.createElement("img");
          element.width = 1026; // 2 pixels extra to close the gap.
          element.src = side.url;
          //CSS3DObject 是拓展出去的方法,原型是object3D,见CSS3DRenderer.js
          var object = new THREE.CSS3DObject(element);
          object.position.fromArray(side.position);
          object.rotation.fromArray(side.rotation);
          scene.add(object);
        }
        //渲染器也是拓展出来的方法,见CSS3DRenderer.js
        renderer = new THREE.CSS3DRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
        //添加鼠标,手势,窗口事件
        document.addEventListener("mousedown", onDocumentMouseDown, false);
        document.addEventListener("wheel", onDocumentMouseWheel, false);
        document.addEventListener("touchstart", onDocumentTouchStart, false);
        document.addEventListener("touchmove", onDocumentTouchMove, false);

        window.addEventListener("resize", onWindowResize, false);
      }

      function onWindowResize() {
        //窗口缩放的时候,保证场景也跟随着一起缩放
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);
      }

      function onDocumentMouseDown(event) {
        event.preventDefault();
        //保证监听拖拽事件
        document.addEventListener("mousemove", onDocumentMouseMove, false);
        document.addEventListener("mouseup", onDocumentMouseUp, false);
      }

      function onDocumentMouseMove(event) {
        //鼠标的移动距离  currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
        var movementX =
          event.movementX || event.mozMovementX || event.webkitMovementX || 0;
        var movementY =
          event.movementY || event.mozMovementY || event.webkitMovementY || 0;
        lon -= movementX * 0.1;
        lat += movementY * 0.1;
      }

      function onDocumentMouseUp(event) {
        //保证监听拖拽事件
        document.removeEventListener("mousemove", onDocumentMouseMove);
        document.removeEventListener("mouseup", onDocumentMouseUp);
      }

      function onDocumentMouseWheel(event) {
        //相机的视觉随着鼠标滚动的距离拉进或者远离
        var fov = camera.fov + event.deltaY * 0.05;
        camera.fov = THREE.Math.clamp(fov, 10, 75);
        camera.updateProjectionMatrix();
      }

      function onDocumentTouchStart(event) {
        event.preventDefault();
        //移动端没有movement,所以直接用touchX touchY去计算移动的距离
        var touch = event.touches[0];
        touchX = touch.screenX;
        touchY = touch.screenY;
      }

      function onDocumentTouchMove(event) {
        event.preventDefault();
        var touch = event.touches[0];
        lon -= (touch.screenX - touchX) * 0.1;
        lat += (touch.screenY - touchY) * 0.1;
        touchX = touch.screenX;
        touchY = touch.screenY;
      }
      //开启动画
      function animate() {
        requestAnimationFrame(animate);
        //自动由左向右横向预览全景
        //lon +=  0.1;
        lat = Math.max(-85, Math.min(85, lat));
        phi = THREE.Math.degToRad(90 - lat); //角度转为弧度制
        theta = THREE.Math.degToRad(lon);
        //在球坐标系中算出相机的聚焦点的坐标
        target.x = Math.sin(phi) * Math.cos(theta);
        target.y = Math.cos(phi);
        target.z = Math.sin(phi) * Math.sin(theta);
        camera.lookAt(target);
        renderer.render(scene, camera);
      }
    </script>
  </body>
</html>

js引入文件部分:

three.js可以自己到官网找一下,内容太多,就不贴出来了

CSS3DRenderer.js内容如下:

(function () {
  const _position = new THREE.Vector3();

  const _quaternion = new THREE.Quaternion();

  const _scale = new THREE.Vector3();

  class CSS3DObject extends THREE.Object3D {
    constructor(element = document.createElement("div")) {
      super();
      this.element = element;
      this.element.style.position = "absolute";
      this.element.style.pointerEvents = "auto";
      this.element.style.userSelect = "none";
      this.element.setAttribute("draggable", false);
      this.addEventListener("removed", function () {
        this.traverse(function (object) {
          if (
            object.element instanceof Element &&
            object.element.parentNode !== null
          ) {
            object.element.parentNode.removeChild(object.element);
          }
        });
      });
    }

    copy(source, recursive) {
      super.copy(source, recursive);
      this.element = source.element.cloneNode(true);
      return this;
    }
  }

  CSS3DObject.prototype.isCSS3DObject = true;

  class CSS3DSprite extends CSS3DObject {
    constructor(element) {
      super(element);
      this.rotation2D = 0;
    }

    copy(source, recursive) {
      super.copy(source, recursive);
      this.rotation2D = source.rotation2D;
      return this;
    }
  }

  CSS3DSprite.prototype.isCSS3DSprite = true; //

  const _matrix = new THREE.Matrix4();

  const _matrix2 = new THREE.Matrix4();

  class CSS3DRenderer {
    constructor(parameters = {}) {
      const _this = this;

      let _width, _height;

      let _widthHalf, _heightHalf;

      const cache = {
        camera: {
          fov: 0,
          style: "",
        },
        objects: new WeakMap(),
      };
      const domElement =
        parameters.element !== undefined
          ? parameters.element
          : document.createElement("div");
      domElement.style.overflow = "hidden";
      this.domElement = domElement;
      const cameraElement = document.createElement("div");
      cameraElement.style.transformStyle = "preserve-3d";
      cameraElement.style.pointerEvents = "none";
      domElement.appendChild(cameraElement);

      this.getSize = function () {
        return {
          width: _width,
          height: _height,
        };
      };

      this.render = function (scene, camera) {
        const fov = camera.projectionMatrix.elements[5] * _heightHalf;

        if (cache.camera.fov !== fov) {
          domElement.style.perspective = camera.isPerspectiveCamera
            ? fov + "px"
            : "";
          cache.camera.fov = fov;
        }

        if (scene.autoUpdate === true) scene.updateMatrixWorld();
        if (camera.parent === null) camera.updateMatrixWorld();
        let tx, ty;

        if (camera.isOrthographicCamera) {
          tx = -(camera.right + camera.left) / 2;
          ty = (camera.top + camera.bottom) / 2;
        }

        const cameraCSSMatrix = camera.isOrthographicCamera
          ? "scale(" +
            fov +
            ")" +
            "translate(" +
            epsilon(tx) +
            "px," +
            epsilon(ty) +
            "px)" +
            getCameraCSSMatrix(camera.matrixWorldInverse)
          : "translateZ(" +
            fov +
            "px)" +
            getCameraCSSMatrix(camera.matrixWorldInverse);
        const style =
          cameraCSSMatrix +
          "translate(" +
          _widthHalf +
          "px," +
          _heightHalf +
          "px)";

        if (cache.camera.style !== style) {
          cameraElement.style.transform = style;
          cache.camera.style = style;
        }

        renderObject(scene, scene, camera, cameraCSSMatrix);
      };

      this.setSize = function (width, height) {
        _width = width;
        _height = height;
        _widthHalf = _width / 2;
        _heightHalf = _height / 2;
        domElement.style.width = width + "px";
        domElement.style.height = height + "px";
        cameraElement.style.width = width + "px";
        cameraElement.style.height = height + "px";
      };

      function epsilon(value) {
        return Math.abs(value) < 1e-10 ? 0 : value;
      }

      function getCameraCSSMatrix(matrix) {
        const elements = matrix.elements;
        return (
          "matrix3d(" +
          epsilon(elements[0]) +
          "," +
          epsilon(-elements[1]) +
          "," +
          epsilon(elements[2]) +
          "," +
          epsilon(elements[3]) +
          "," +
          epsilon(elements[4]) +
          "," +
          epsilon(-elements[5]) +
          "," +
          epsilon(elements[6]) +
          "," +
          epsilon(elements[7]) +
          "," +
          epsilon(elements[8]) +
          "," +
          epsilon(-elements[9]) +
          "," +
          epsilon(elements[10]) +
          "," +
          epsilon(elements[11]) +
          "," +
          epsilon(elements[12]) +
          "," +
          epsilon(-elements[13]) +
          "," +
          epsilon(elements[14]) +
          "," +
          epsilon(elements[15]) +
          ")"
        );
      }

      function getObjectCSSMatrix(matrix) {
        const elements = matrix.elements;
        const matrix3d =
          "matrix3d(" +
          epsilon(elements[0]) +
          "," +
          epsilon(elements[1]) +
          "," +
          epsilon(elements[2]) +
          "," +
          epsilon(elements[3]) +
          "," +
          epsilon(-elements[4]) +
          "," +
          epsilon(-elements[5]) +
          "," +
          epsilon(-elements[6]) +
          "," +
          epsilon(-elements[7]) +
          "," +
          epsilon(elements[8]) +
          "," +
          epsilon(elements[9]) +
          "," +
          epsilon(elements[10]) +
          "," +
          epsilon(elements[11]) +
          "," +
          epsilon(elements[12]) +
          "," +
          epsilon(elements[13]) +
          "," +
          epsilon(elements[14]) +
          "," +
          epsilon(elements[15]) +
          ")";
        return "translate(-50%,-50%)" + matrix3d;
      }

      function renderObject(object, scene, camera, cameraCSSMatrix) {
        if (object.isCSS3DObject) {
          const visible = object.visible && object.layers.test(camera.layers);
          object.element.style.display = visible ? "" : "none";

          if (visible) {
            object.onBeforeRender(_this, scene, camera);
            let style;

            if (object.isCSS3DSprite) {
              _matrix.copy(camera.matrixWorldInverse);

              _matrix.transpose();

              if (object.rotation2D !== 0)
                _matrix.multiply(_matrix2.makeRotationZ(object.rotation2D));
              object.matrixWorld.decompose(_position, _quaternion, _scale);

              _matrix.setPosition(_position);

              _matrix.scale(_scale);

              _matrix.elements[3] = 0;
              _matrix.elements[7] = 0;
              _matrix.elements[11] = 0;
              _matrix.elements[15] = 1;
              style = getObjectCSSMatrix(_matrix);
            } else {
              style = getObjectCSSMatrix(object.matrixWorld);
            }

            const element = object.element;
            const cachedObject = cache.objects.get(object);

            if (cachedObject === undefined || cachedObject.style !== style) {
              element.style.transform = style;
              const objectData = {
                style: style,
              };
              cache.objects.set(object, objectData);
            }

            if (element.parentNode !== cameraElement) {
              cameraElement.appendChild(element);
            }

            object.onAfterRender(_this, scene, camera);
          }
        }

        for (let i = 0, l = object.children.length; i < l; i++) {
          renderObject(object.children[i], scene, camera, cameraCSSMatrix);
        }
      }
    }
  }

  THREE.CSS3DObject = CSS3DObject;
  THREE.CSS3DRenderer = CSS3DRenderer;
  THREE.CSS3DSprite = CSS3DSprite;
})();

效果:

3d空间图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白的蓝色生活

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值