首页 > 代码库 > 关于3D Panorama(全景)

关于3D Panorama(全景)

蟹蟹 https://aotu.io/notes/2016/08/24/2016-8-24-css-3d-panorama/

 

 

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=640, target-densitydpi=device-dpi, user-scalable=no">
  <title>全景</title>
  <link rel="stylesheet" href="http://jdc.jd.com/lab/zaowu/dist/css/reset.min.css">
  <style>
  html,
  body {
    width: 100%;
    height: 100%;
  }
  
  body {
    background-size: cover;
    -webkit-user-select: none;
    user-select: none;
    padding-top: 150px;
    overflow: hidden;
  }


  #view{
    width: 800px;
    height: 500px;
    overflow: hidden;
    margin:  0 auto;
    perspective: 420px;

  }
  #bigCube{
    width: 6000px;
    height: 6000px;
    margin-left: -2600px;
    margin-top: -2750px;
    transform-origin: 3000px 3000px;
    transform-style: preserve-3d;
  }
  #cube{
    width: 6000px;
    height: 6000px;
    position: relative;
    transform-style: preserve-3d;
  }
  .stage{
    width: 6000px;
    height: 6000px;
    transform-style: preserve-3d;
  }
  .container {
    width: 800px;
    height: 500px;
    position: absolute;
    transform-style: preserve-3d;
  }
  
  .container>div {
    width: 100%;
    height: 100%;
    position: absolute;
  }
  </style>
</head>

<body>
<div id="view">
  <div id="bigCube">
    <div id="cube">
       <div class="stage">
          <div class="container">
            
          </div>
        </div>
    </div>
  </div>
</div>

  <script src="http://jdc.jd.com/lab/zaowu/dist/js/jquery-3.1.0.min.js"></script>
  <!-- <script src="http://www.mamicode.com/dist/js/zepto.min.js"></script> -->
  <script>
    //禁用微信的下拉
    $(‘body‘).on(‘touchmove‘, function(event) {
      event.preventDefault();
    });

    var BG_WIDTH = 3000,
      BG_HEIGHT = 3000,
      BG_NUMBER = 4,
      PER_ANGLE = 360 / BG_NUMBER;

    var translateZ = (function calTranslateZ(opts) {
      return Math.round(opts.width / (2 * Math.tan(Math.PI / opts.number)))
    })({
      width: BG_WIDTH,
      number: BG_NUMBER
    })
    console.log(translateZ);


    var view = $("#bigCube")
      viewW = view.width(),
      viewH = view.height();


    var container = $(".container"),
      bgItem;

    for (var i = 0; i < BG_NUMBER; i++) {
      $("<div></div>").css({
        "background": "url(http://jdc.jd.com/lab/zaowu/dist/images/panorama/"+ i +".jpg) 0 0/cover no-repeat",
        "position": "absolute",
        "width": BG_WIDTH,
        "height": BG_HEIGHT,
        "left": (viewW - BG_WIDTH) / 2,
        "top": (viewH - BG_HEIGHT) / 2,
        "transform": "rotateY(" + (180 - i * PER_ANGLE) + "deg) translateZ("+ (-translateZ +10 ) +"px)", // translateZ + 10 是为了去掉模模块间的缝隙
        // "backface-visibility": "hidden"
      }).appendTo(".container")
    }

    for(var j = 0; j < 2; j++){
      $("<div></div>").css({
        "background": "url(http://jdc.jd.com/lab/zaowu/dist/images/panorama/"+ (j + 4) +".jpg) 0 0/cover no-repeat",
        "position": "absolute",
        "width": BG_WIDTH,
        "height": BG_HEIGHT,
        "left": (viewW - BG_WIDTH) / 2,
        "top": (viewH - BG_HEIGHT) / 2,
        "transform": "rotateX("+ (j ? 1: -1) * 90 +"deg) rotateZ(90deg) translateZ("+ (-translateZ+10) +"px)" // translateZ + 10 是为了去掉模模块间的缝隙
      }).appendTo(".container")
    }
    bgItem = container.find(‘div‘)


  
    var lastMouseX = 0,
      lastMouseY = 0,
      curMouseX = 0,
      curMouseY = 0,
      lastAngleX = 0,
      lastAngleY = 0,
      angleX = 0,
      angleY = 0;

    var initTranZ = -150,
      tranZDistance = 0;
    var temZ = 0;

    var slastMouseX = 0;
    var frameTimer;
    var timeoutTimer;

    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame ||
      function(callback) {
        setTimeout(callback, 1000 / 60)
      }

    $(document).on("mousedown touchstart", mouseDownHandler)
    $(document).on("mouseup touchend", mouseUpHandler)

    function mouseDownHandler(evt) {
      // 由于移动设备支持多指触摸,因此与PC的鼠标不同,返回是一数组touches。
      lastMouseX = evt.pageX || evt.touches[0].pageX;
      lastMouseY = evt.pageY || evt.touches[0].pageY;
      lastAngleX = aimAngleX;
      lastAngleY = aimAngleY;
      curMouseX = evt.pageX || evt.touches[0].pageX;
      curMouseY = evt.pageY || evt.touches[0].pageY;

      slastMouseX = evt.pageX || evt.touches[0].pageX;
      clearTimeout(timeoutTimer)

      $(document).on("mousemove touchmove", mouseMoveHandler)
      window.cancelAnimationFrame(frameTimer)
      frameTimer = requestAnimationFrame(go)
    }

    function mouseMoveHandler(evt) {
      curMouseX = evt.pageX || evt.touches[0].pageX;
      curMouseY = evt.pageY || evt.touches[0].pageY;

      dragRotate({
        pageX: curMouseX,
        pageY: curMouseY
      });

    }

    function mouseUpHandler(evt) {
      // touchend 不具有坐标信息,因此需以touchmove的最后一次点提供
      // http://stackoverflow.com/questions/17957593/how-to-capture-touchend-coordinates
      // curMouseX = evt.pageX || evt.touches[0].pageX;
      // curMouseY = evt.pageY || evt.touches[0].pageY;

      $(document).unbind("mousemove touchmove")

      timeoutTimer = setTimeout(function(){
        window.cancelAnimationFrame(frameTimer)
      }, 2500)
    }

    

    var aimAngleX = 0,aimAngleY = 0;
    var curBgAngleX = 0, curBgAngleY = 0;
    var curItemAngleX = 0, curItemAngleY = 0;
    function dragRotate(evtInfo) {
      // 注意:rotateX(Y) 与 鼠标(触摸)的X(Y)轴是交叉对应的

      // aimAngleX(Y)的值是通过【拖拽位移换算为相应角度得到】
      aimAngleX = ( 180 / Math.PI * (Math.atan((curMouseX - lastMouseX) / translateZ)) + lastAngleX )

      // console.log((180 / Math.PI * Math.atan((curMouseY - lastMouseY) / (Math.sqrt(Math.pow(panoBgItemH / 2, 2) + Math.pow(translateZ, 2))*1.5)) + lastAngleY), 30)
      // 限制上下旋转监督在30°以内
      aimAngleY = Math.max(-60, Math.min((180 / Math.PI * Math.atan((curMouseY - lastMouseY) / (Math.sqrt(Math.pow(BG_HEIGHT / 2, 2) + Math.pow(translateZ, 2))*1.5)) + lastAngleY), 60))
    }


    // loop
    function go() {

      // bg 与 item 的位移增量速度的不一致,可形成视差运动
      curBgAngleX += (aimAngleX - curBgAngleX) * 0.5;
      curBgAngleY += (aimAngleY - curBgAngleY) * 0.5;

      $("#cube").css({
        transform: "rotateX(" + (curBgAngleY) + "deg) rotateY(" + -curBgAngleX + "deg) rotateZ(0)"
      })

  
      frameTimer = requestAnimationFrame(go);
    }

  </script>
</body>

</html>

关于3D Panorama(全景)