HTML5 круговая панорама на three.js

от автора

    В последнее время все чаще можно наткнуться на круговую панораму в интернете. Взять к примеру тот же сырный домик. Это эффектная штучка возможно вскоре станет обыкновенным делом для сайтов ресторанов, гостиниц, отелей и т. п. Однако, что делать, если существуют проблемы с flash на компьютере? Это реальная ситуация, которая возникла у меня на работе, по причине жесткой политики безопасности IT-отдела.
   &nbspВ этой небольшой статье я расскажу вам о трудностях, которые встретил на пути создания интерактивной панорамы на WebGL + THREE.js.

Определим требования к панораме:

  • используем WebGL, так как Canvas панорамы просто ужас, и еще новый IE поддерживает;
  • Просмотр панорамы путем перетаскиванием зажатой кнопки мыши;
  • Активные элементы призванные обратить внимание и сообщить информацию;
  • Возможность посмотреть несколько панорам на одной странице.

    Что бы понять, как это реализовать, предлагаю представить следующее: «Мы находимся в центре сферы, на внутреннюю поверхность которой нанесена текстура панорамы. Мы — это камера, которая может поворачиваться и смотреть вверх или вниз. На внутренней поверхности сферы ( „у“ поверхности, как оказалось ) находятся элементы, и когда мы наводим на них мышку, появляется окошко с информацией».

Cфера

    Существует как минимум два варианта реализации панорамы: кубическая и сферическая. Я выбрал сферическую, так как размещение визуально одинаковых активных элементов предполагает равноудаленное расстояние от центра. За прототип возьмем существующий образец панорамы с сайта разработчика библиотеки. Он нам полностью подходит за одним исключением. Это сфера с текстурой вывернутая на изнанку. Трудно представить как это может выглядеть.

mesh.scale.x = -1; 

    К сожалению, одна эта деталь ставит полный крест на возможности добавления элементов. Суть в том, что получить хоть какую то информацию об объекте в пространстве при помощи указателя, надо «выстрелить» лучом (Raycaster) из точки указателя в направление вектора, только в данном случае луч не ударится о стенку сферы, потому как камера (логичная точка начала) не находится внутри. Сделано это потому, что текстура натягивается только с внешней стороны, но теперь есть возможность это исправить просто добавив свойство side в объект материи сферы:

mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( {      map: THREE.ImageUtils.loadTexture( 'textures/2294472375_24a3b8ef46_o.jpg' )     side: THREE.BackSide  } ) ); 

Кстати, это типичное создание объекта в мире THREE.js. Как правило создается геометрия объекта, материал ( текстура ), а потом добавляется на сцену.

Элементы

Теперь надо подумать о том, что из себя будут представлять те самые активные элементы. В идеале ими должны быть плоские спрайты, всегда отображающиеся лицом к камере. Да, да именно так 🙂

image

    Но здесь нас ждет сюрприз. В THREE.js существует два «класса» для рендеринга: WebGLRenderer и CanvasRenderer. И два типа простых объектов: Particle (частица) и Sprite. WebGL работает с Sprite, а Canvas с Particle. При этом нам необходим именно WebGL, а объект Sprite не имеет объема в пространстве. То есть по нему невозможно попасть мышкой.
    Что ж возьмем и с имитируем эти самые спрайты при помощи 3D объекта с геометрией плоскости ( PlaneGeometry):

var itemGeometry = new THREE.PlaneGeometry(35, 35),       pointMapHovered = THREE.ImageUtils.loadTexture( "img/information-hover.PNG" ),       pointMap = THREE.ImageUtils.loadTexture( "img/information-unhover.PNG" );  point = new THREE.Mesh( itemGeometry, new THREE.MeshBasicMaterial({           map: pointMap,           transparent:true  //планка квадратная, не думаю, что кому-нибудь понравятся черные углы         }) ); 

    Хочу обратить ваше внимание, почему именно так: закеширована геометрия точки и текстура, а материал будет каждый раз создаваться заново. Дело в том, что при наведении мышки на точку, мы будем подменять текстуру на более яркую, к примеру, но если MeshBasicMaterial закеширована и является для всех общей, загораться будут все. Насчет наведения мышкой, все просто — берем отсюда.
    Последняя важная часть, которая вызвала затруднения — это перерасчет координат области панорамы на странице на координаты WebGL пространства для точного выделения точек. Визуально элементы видны, но их координаты на страничке не совпадают с координатами 3D пространства. На StackOverFlow нашелся ответ.

Данные

     Так как предполагается возможность просматривать много панорам на одной странице, лучше все данные поместить в JSON. Примерно так:

{ "points": [                   {                    "coords": {                        "x": 302.0282521739266,                        "y": -32.30522607035554,                         "z": 389.86440214968525                     },                        "header": "Заголовок",                        "body": "Описание."                  },             ], "texture": "panorama.jpg", "name": "название панорамы" } 

    Что бы просматривать разные панорамы, мы будем подменять текстуру сферы, удалять точки и по координатам выстраивать новые.

Что получилось

Приглашаю посмотреть

Демо

Заранее прошу прощения за использованные материалы. Описание хлебобулочного завода #7, как и его название придумано из головы, любые совпадения случайны и не имеют никакой связи с реальностью. ссылка

ссылка на оригинал статьи http://habrahabr.ru/post/184488/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *