调整浏览器窗口大小时,ThreeJS画布的定位偏差是什么原因?

时间:2017-01-10 06:55:07

标签: javascript html 3d three.js html5-canvas

基本上我正在尝试对齐ThreeJS画布(蓝色背景和黄色文本),以便它紧贴绿色图像的透明切口。到目前为止,这对我来说效果很好,但是我注意到当我调整浏览器窗口或缩放时,画布的位置会略微偏斜。例如,将窗口调整得较小会显示顶部和左侧画布周围的间隙。

理想情况下,我只希望蓝色画布始终显示在与调整窗口大小相同的相对位置。

Codepen演示问题:http://codepen.io/joeycato/pen/pRjmYP

<html lang="en">
<head>
  <meta charset="UTF-8">
  <style type="text/css">
      .app {
         background-color: orange
      }
      body {
        color: green;
        overflow: hidden; 
        background-color: black
      }
      .backgroundImage {
          position: absolute;
          top: 0%; 
          left: 0%;
          width: 100%; 
          height: auto;
          max-width: 100%;
      }
  </style>
  <script src="three-r83.min.js"></script>
  <script src="jquery-3.1.1.min.js"></script>
  <script src="app.js"></script>
</head>
<body>
    <img id="imgBackground" src="background.png" class="backgroundImage"/>
    <div class="app" />
</body>
</html>

使用Javascript:

let game,
  BACKGROUND_IMAGE_WIDTH = 1280,
  BACKGROUND_IMAGE_HEIGHT = 736,
  BACKGROUND_IMAGE_ASPECT_RATIO = BACKGROUND_IMAGE_HEIGHT / BACKGROUND_IMAGE_WIDTH,
  ctx,
  camera, scene, renderer, geom, materialTube, textureTube, mesh,
  canvasMain;

function mainLoop() {
  ctx.clearRect(0, 0, 256, 256);
  ctx.fillStyle = 'blue';
  ctx.fillRect(0, 0, 256, 256);

  ctx.font = '12pt Arial';
  ctx.fillStyle = 'yellow';
  ctx.fillText('GREEN STENCIL OVERLAYING', 0, 100);
  ctx.fillText('BLUE THREEJS CANVAS', 20, 120);
  ctx.fillText('RESIZING WINDOW SMALLER', 10, 180);
  ctx.fillText('REVEALS GAPS ON SIDE', 10, 200);

  textureTube.needsUpdate = true;
  renderer.render(scene, camera);

  requestAnimationFrame(mainLoop);
}

function initScene() {
  var demoWidth = window.innerWidth;
  var demoHeight = window.innerHeight;

  // Forcing height to match aspect ratio of original iamge (1280x736)
  demoHeight = BACKGROUND_IMAGE_ASPECT_RATIO * demoWidth;

  if (camera) {
    scene.remove(camera);
  }

  camera = new THREE.PerspectiveCamera(55, demoWidth / demoHeight, 1, 1000);

  camera.position.x = -110;
  camera.position.y = 30;
  camera.position.z = 457;

  scene.add(camera);

  geom = new THREE.PlaneGeometry(170, 210);
  geom.verticesNeedUpdate = true;

  if (mesh) {
    scene.remove(mesh);
  }

  mesh = new THREE.Mesh(geom, materialTube);
  mesh.rotation.x = 0.13999999999999999;
  mesh.rotation.y = -0.4900000999999998;
  mesh.rotation.z = -0.04999899999999999;

  scene.add(mesh);

  renderer.setSize(demoWidth, demoHeight);
}

function makeCanvas(id, w, h) {
  let elem = document.createElement('canvas');
  elem.id = id;
  elem.width = w;
  elem.height = h;
  return elem;
}

(function($) {
  $(function() {
    canvasMain = makeCanvas('canvasMain', 256, 256);
    ctx = canvasMain.getContext('2d');

    renderer = new THREE.WebGLRenderer();
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    textureTube = new THREE.Texture(canvasMain);
    materialTube = new THREE.MeshBasicMaterial({
      map: textureTube
    });

    initScene();
    requestAnimationFrame(mainLoop);
  });
})(jQuery);

window.addEventListener('resize', function() {
  initScene();
});

// requestAnimationFrame
(function() {
  var lastTime = 0;
  var vendors = ['ms', 'moz', 'webkit', 'o'];
  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
      window[vendors[x] + 'CancelRequestAnimationFrame'];
  }
  if (!window.requestAnimationFrame)
    window.requestAnimationFrame = function(callback, element) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = window.setTimeout(function() {
          callback(currTime + timeToCall);
        },
        timeToCall);
      lastTime = currTime + timeToCall;
      return id;
    };

  if (!window.cancelAnimationFrame)
    window.cancelAnimationFrame = function(id) {
      clearTimeout(id);
    };

}());

1 个答案:

答案 0 :(得分:0)

看起来倾斜是身体默认边距设置的直接结果。

添加body { margin: 0 }解决了我的问题。