Как включить разрешение retina render.setSize на iPhone с помощью threejs - PullRequest
0 голосов
/ 03 марта 2020

Используя три js, можно нарисовать холст в два раза больше, но как затем уменьшить его с помощью css, чтобы он отображался в правильном разрешении для iPhone.

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

В результате получается пиксельное изображение, и это работает:

renderer.setSize(window.innerWidth*2, window.innerHeight*2);

тогда холст слишком велик для экрана, и я не могу получить css, чтобы правильно уменьшить его. Не говоря уже о том, что делать это на ноутбуке с дисплеем Retina было бы дьявольским. Это потому, что он использует WebGL для рисования на экране?

Как разместить эти различные плотности пикселей в трех js?

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Если бы это был я, я бы позволил CSS установить размер холста. Затем я спросил бы браузер, какой размер холста

const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;

, и соответственно установил бы размер буфера рисования холста, используя

renderer.setSize(desiredWidth, desiredHeight, false);

. В конце важно передать false так что три. js не испортят CSS

Более того, я бы никогда не использовал setPixelRatio, потому что это просто вызывает ошибки и неоднозначность. Вместо этого я бы вычислил нужный мне размер и использовал бы этот размер. Пример

const pixelRatio = window.devicePixelRatio;
const desiredWidth = canvas.clientWidth * pixelRatio | 0;
const desiredHeight = canvas.clientHeight * pixelRatio | 0;
renderer.setSize(desiredWidth, desiredHeight, false);

Зачем использовать CSS и посмотреть размер?

Используя CSS ваш код работает во всех случаях. Если вы хотите, чтобы ваш холст работал в полноэкранном режиме, или вы хотите, чтобы ваш холст представлял собой диаграмму в абзаце, или вы хотите, чтобы ваш холст можно было растягивать во flexbox или сетке, независимо от того, как вы это делаете, вы получите правильный размер.

Почему бы не использовать setPixelRatio?

Когда вы используете setPixelRatio, у вас теперь есть буфер рисования холста, размер которого отличается от указанного вами. Есть много ситуаций, когда вам нужно знать фактический размер. Это включает в себя использование определенных видов эффектов, считывание пикселей для выбора графического процессора, возможно создание снимков экрана, рисование с точками и т. Д. c ... Когда вы используете setPixelRatio, вы действительно не знаете, какого размера окажется буфер рисования холста. Да, вы считаете, код будет просто умножаться на соотношение пикселей устройства, но округляется ли он? округлить вниз? Это изменится завтра? Ты понятия не имеешь. Таким образом, не используя его, вы знаете, какой размер холста. Это всегда тот размер, который вы указали при вызове setSize. Это означает, что вы можете использовать этот размер везде. Вам не нужно угадывать, когда уместно использовать указанный размер и когда вам нужно делать другую математику. Обратите внимание, что если вы ошиблись в математике, ваше приложение может работать на устройстве с соотношением пикселей 1, но не работать на устройстве с другим соотношением пикселей. Если не использовать setPixelRatio, то эти ошибки становятся невозможными.

Возможно, вы вообще не захотите устанавливать соотношение пикселей

Если соотношение пикселей равно 2, устройству необходимо отрисовать пиксели в 4 раза больше, чем с Пиксельное соотношение 1. Если пиксельное отношение равно 3, это dr aws 9x пикселей. Некоторые устройства даже имеют пиксель устройства rat ios, равный 3,5 или 4, что в 16 раз больше пикселя. Это может сделать вашу страницу работать очень медленно. Слепая установка отношения пикселей только потому, что устройство имеет высокое соотношение пикселей, является рецептом для медленных страниц. Немногие нативные игры делают это, потому что они просто работают слишком медленно. Часто целесообразно не устанавливать его.

Пример:

html, body {
  margin: 0;
  height: 100%;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}
<canvas id="c"></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r113/build/three.module.js';

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(-1, 2, 4);
    scene.add(light);
  }

  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

  function makeInstance(geometry, color, x) {
    const material = new THREE.MeshPhongMaterial({color});

    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    cube.position.x = x;

    return cube;
  }

  const cubes = [
    makeInstance(geometry, 0x44aa88,  0),
    makeInstance(geometry, 0x8844aa, -2),
    makeInstance(geometry, 0xaa8844,  2),
  ];

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const pixelRatio = window.devicePixelRatio;
    const width  = canvas.clientWidth  * pixelRatio | 0;
    const height = canvas.clientHeight * pixelRatio | 0;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    cubes.forEach((cube, ndx) => {
      const speed = 1 + ndx * .1;
      const rot = time * speed;
      cube.rotation.x = rot;
      cube.rotation.y = rot;
    });

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
</script>
1 голос
/ 03 марта 2020

Вы можете использовать что-то вроде этого, которое будет устанавливать соотношение пикселей в зависимости от того, что устройство может поддерживать:

renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );

Убедиться, что холст не в два раза больше размера вашего документа, будет немного CSS следующим образом:

canvas {
  display: block;
}

Есть много способов сделать это. Вот еще один пример - https://codepen.io/Staak/pen/wNvZVP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...