Шаг за шагом реализуйте панорамный просмотр веб-страниц — three.js

JavaScript three.js

Я считаю, что все знакомы с 2D-рисованием на холсте, но 3D-мир еще круче. Начнем непосредственно с three.js. Начнем с 0, чтобы исследовать трехмерный мир

1. Основные понятия

В THREEjs необходимыми элементами для рендеринга 3D-мира являются сцена, камера и рендерер. После рендеринга 3D-мира вы можете добавить к нему различные объекты, источники света и т. д., чтобы сформировать 3D-мир:

Сцена: Правосторонняя система координат, все элементы находятся в сцене, эквивалентной «миру», включая различные вещества и физические изменения.

// 创建场景
const scene = new THREE.Scene();

Камера: камера эквивалентна человеческому глазу, только с камерой можно увидеть все объекты и источники света в сцене. Обычно используются ортогональные и перспективные камеры.

Орфографическая камера представляет собой прямоугольную область просмотра, и объекты видны только в пределах этой области.Объекты визуализируются в одном размере независимо от того, насколько далеко или близко находится камера. Общий сценарий применения — 2.5d игры, такие как прыжки, механические модели

// 创建正交相机
const camera = new THREE.OrthographicCamera(
    -window.innerWidth / 200,
    window.innerWidth /200 ,
    window.innerHeight/ 200,
    -window.innerHeight/ 200,
    1,
    1000
);

Мы можем видеть эффект изображения выше, есть куб, который прошел долгий путь, но размер остался прежним. Кроме того, вы можете видеть, что куб в углу был усечен, потому что орфографическая камера показывает сцену только в одном пространстве, поэтому будет эффект усечения.

перспективная камераЭто наиболее часто используемый тип камеры, имитирующий зрение человеческого глаза, близкое большое и далекое маленькое (перспектива). Fov представляет собой угол зрения.Чем больше Fov, тем шире глаза, чем дальше они находятся и тем больше они могут видеть. Если вам нужно имитировать реальность, в основном используйте эту камеру

// 创建透视相机
const camera = new THREE.PerspectiveCamera(
          90,
          window.innerWidth / window.innerHeight,
          1,
          10000
        );

Выходит эффект ближнего большого и дальнего малого, что больше соответствует действительности

Рендерер

Наконец, весь контент должен быть отрендерен на странице, и нужен рендерер:

      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight); // canvas大小
      document.body.appendChild(renderer.domElement);

2. Добавьте контент на экран

Выше действительно нарисован трехмерный мир, но на нем ничего нет. В three.js нам нужно добавить источники света и сетки.

mesh

сетка есть сетка. В компьютере трехмерный мир состоит из точек с бесчисленными гранями, сшитыми вместе, чтобы сформировать объекты различной формы. Эта модель называется моделью сетки. Линия состоит из двух точек, поверхность состоит из 3 точек, а объект состоит из нескольких поверхностей, состоящих из 3 точек:

Сетка (mesh) состоит из геометрии (geometry) и материала (material)

geometry

Геометрия, которую мы можем вообразить, поставляется с фреймворком, и нам нужно только вызвать соответствующий конструктор геометрии, чтобы создать ее. Все методы создания геометрии новые, такие как BoxBuffer:

const geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );

При создании он обычно определяет основные данные, необходимые для визуализации 3D-объекта: поверхность грани, вершины вершин и другую информацию. THREE.xxxGeometry относится к геометрии, поставляемой с фреймворком.Параметры, требуемые для разных геометрий, различаются, вероятно, ширина, высота, радиус, глубина, сегмент, детали, угол и другие атрибуты.

Дополнительные API, связанные с геометрией

В чем разница между BufferGeometry и Geometry?Все они одинаковы с точки зрения эффекта, но BufferGeometry имеет больше атрибутов вершин и более высокую производительность. Для разработчиков лучше использовать меньше свойств объекта Geometry. Когда THREE анализирует объект геометрии, если это геометрия, он преобразует объект в объект ufferGeometry, а затем переходит к следующему рендерингу.

material

Многие физические свойства объекта зависят от его материала, который также определяет внешний вид геометрии. Метод создания материала также новый, например, материал Ламберта:

const material = new THREE.MeshLambertMaterial();

Наличие у объекта таких свойств, как зеркальность, яркость, цвет, прозрачность и отражение, зависит от того, какой материал используется. THREE.xxxMaterial относится к материалу, который поставляется с рамой, и параметры, требуемые для разных материалов, также различаются.

Дополнительные API, связанные с материалами

С помощью геометрии и материала можно создать сетку и добавить ее к сцене:

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

источник света

Трехмерный мир, если он должен быть более реалистичным, нуждается в источнике света. Существует также много видов света, распространенными являются параллельный свет (рис. 2), точечный источник света (рис. 3), окружающий свет (окружающий свет заполняет все геометрические поверхности), точечный свет (рис. 1)

Среди них только параллельный свет и точечные источники света могут давать тени. А на некоторые материалы влияет источник света, и света нет, он черный. И некоторые материалы не подвержены влиянию света. Создание источников света, таких как прямой свет:

const light = new THREE.DirectionalLight(0xffffff, 0.9)

THREE.xxxLight относится к конструктору источника света, который поставляется с фреймворком.Как правило, параметры, необходимые для создания экземпляра, — это цвет, интенсивность, расстояние и другие конфигурации. Кроме того, 3D-мир, конечно же, не является разновидностью световой композиции, поэтому свет можно накладывать, а результат наложения можно применять к объектам.

И тень объекта не свободна, ему нужен свет, поддерживающий тень плюс конфигурация разработчика:

// 光产生影子
light.castShadow = true;
// 地面接受影子
ground.receiveShadow = true;
// 物体产生影子
mesh.castShadow = true;

Дополнительные API, связанные с источниками света

Дополнительные API, связанные с тенями

3. Инструменты отладки

трековый контроллер

С помощью этого контроллера вы можете перетаскивать весь экран, перетаскивая и прокручивая мышью. Код контроллера дорожки находится вТРИ официальных гитхабаВключено, если сообщается об ошибке при использованииTHREE.OrbitControls is not a constructor, затем сделайте копию и добавьте окно в первую строку:window.THREE.OrbitControls = ...

Способ его использования — создать новый контроллер, затем прослушать изменения и запустить рендеринг.

        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.addEventListener("change", () => {
          renderer.render(scene, camera);
        });
        controls.minDistance = 1;
        controls.maxDistance = 2000;
        controls.enablePan = false;

мониторинг производительности

исходный код. Можно скопировать и повесить на окно

В большинстве официальных примеров используется плагин статистики, и кривая изменения производительности появится в верхнем левом углу для отладки. Инструкции:

    const stat = new Stats();
    document.body.appendChild(stat.dom);
    
    // 改造render函数
    function render() {
      renderer.render(scene, camera);
      stat.update();
    }

4. let's coding

Сначала вытащите сцену, камеру, рендерер, затем добавьте красный шар.

      function init() {
      const renderer = new THREE.WebGLRenderer();
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      // 场景
      const scene = new THREE.Scene();
      // 相机
      const camera = new THREE.PerspectiveCamera(
        90,
        window.innerWidth / window.innerHeight,
        0.1,
        100
      );
      camera.position.set(10, 0, 0);

      // 轨道控制器
      const controls = new THREE.OrbitControls(camera, renderer.domElement);
      controls.addEventListener("change", render);
      controls.minDistance = 1;
      controls.maxDistance = 200;
      controls.enablePan = false;

      // 新增一个红色球
      const geometry = new THREE.SphereGeometry(1, 10, 10);
      const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
      // 坐标轴辅助线
      scene.add(new THREE.AxisHelper(1000));

      controls.update(); // 控制器需要
      controls.target.copy(mesh.position);

      function render() {
        renderer.render(scene, camera);
      }

      function r() {
        render();
        requestAnimationFrame(r)
      }
      r()
    }
    
    init();

На данный момент вы можете видеть, что в исходу координат есть мяч. На самом деле, текстура геометрии может использовать изображения или даже видео. В это время вы не можете дважды щелкнуть, чтобы открыть HTML, и вам нужно открыть локальный сервер. Давайте преобразуем сетку:

    function addImg(url, scene, n = 1) {
      const texture = THREE.ImageUtils.loadTexture(url);
      const material = new THREE.MeshBasicMaterial({ map: texture });
      const geometry = new THREE.SphereGeometry(1, 10, 10);
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
      return mesh;
    }
    
    
      // const geometry = new THREE.SphereGeometry(1, 10, 10);
      // const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
      // const mesh = new THREE.Mesh(geometry, material);
      // 去酷家乐找了一个图
      const mesh = addImg("https://qhyxpicoss.kujiale.com/r/2019/07/01/L3D137S8ENDIADDWAYUI5L7GLUF3P3WS888_3000x4000.jpg?x-oss-process=image/resize,m_fill,w_1600,h_920/format,webp", scene, 1); 
      scene.add(mesh);

Исходная точка показывает график в виде текстурированной сферы

В принципе все ок, как добиться панорамного просмотра? Наши вышеперечисленные условия все в порядке, последнее, что нам нужно сделать, это: поместить камеру в центр сферы, установить минимальный и максимальный пределы масштабирования контроллера орбиты на 1 и 2 и визуализировать внутреннюю поверхность меша.

    // 调整max
      controls.minDistance = 1;
      // controls.maxDistance = 200;
      controls.maxDistance = 2;
      
      // 调整球大小
      // const geometry = new THREE.SphereGeometry(1, 10, 10);
      const geometry = new THREE.SphereGeometry(50, 256, 256);
      
      // 摄像机放球体中心
      // camera.position.set(10, 0, 0);
      camera.position.set(-0.3, 0, 0);
      
      // 渲染球体的双面
      const material = new THREE.MeshLambertMaterial({ map: texture });
      material.side = THREE.DoubleSide;

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

Это всего лишь идея реализации.Существует множество способов ее реализации,таких как цилиндры и кубы.Картинка может быть веерообразной панорамой или комбинацией нескольких картинок. Конкретные детали корректируются в соответствии с бизнесом

Весь код выглядит следующим образом:Нужно ввести три.js, OrbitControl

Все коды
    function init() {
      const renderer = new THREE.WebGLRenderer();
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(
        90,
        window.innerWidth / window.innerHeight,
        0.1,
        100
      );
      // camera.position.set(10, 0, 0);
      camera.position.set(-0.3, 0, 0);

      const controls = new THREE.OrbitControls(camera, renderer.domElement);
      controls.addEventListener("change", render);
      controls.minDistance = 1;
      // controls.maxDistance = 200;
      controls.maxDistance = 2;
      controls.enablePan = false;

      // const geometry = new THREE.SphereGeometry(1, 10, 10);
      // const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
      // const mesh = new THREE.Mesh(geometry, material);
      const mesh = addImg("https://qhyxpicoss.kujiale.com/r/2019/07/01/L3D137S8ENDIADDWAYUI5L7GLUF3P3WS888_3000x4000.jpg?x-oss-process=image/resize,m_fill,w_1600,h_920/format,webp", scene, 1);
      scene.add(mesh);

      controls.update();
      controls.target.copy(mesh.position);

      function render() {
        renderer.render(scene, camera);
      }

      function r() {
        render();
        requestAnimationFrame(r)
      }
      scene.add(new THREE.AxisHelper(1000));
      r()
    }

    function addImg(url, scene, n = 1) {
      const texture = THREE.ImageUtils.loadTexture(url);
      const material = new THREE.MeshBasicMaterial({ map: texture });
      // const geometry = new THREE.SphereGeometry(1, 10, 10);
      const geometry = new THREE.SphereGeometry(50, 256, 256);
      const mesh = new THREE.Mesh(geometry, material);
      material.side = THREE.DoubleSide;
      scene.add(mesh);
      return mesh;
    }

    init();

Обратите внимание на официальный аккаунт «Другой интерфейс», изучите интерфейс с другой точки зрения, быстро растем, играйте в новейшие технологии и исследуйте различные черные технологии вместе.