Компьютерные 3D-комнаты, визуализированные с помощью WebGL, сейчас не являются чем-то новым. Основная цель этой статьи — объяснить проблему глаза и центра в 3D-компьютерных комнатах, которые случайно использовались в проекте. Поразмыслив над этим некоторое время, наконец, я. чувствую, что этот пример лучше всего соответствует моим требованиям, поэтому я использую его в качестве записи.
визуализацииДемонстрация этого компьютерного 3D-зала довольно хороша, она красива, и базовые взаимодействия удовлетворительны. Давайте посмотрим, как ее реализовать.
генерация кода Определить классСначала откройте соответствующие js-файлы один за другим по пути js, указанному в index.html. Класс Editor.Server настраивается в server.js и создается функцией ht.Default.def, инкапсулированной HT (обратите внимание, что созданный класс). имя — Editor. Редактор перед .Server нельзя заменить на E):
ht.Default.def('Editor.Server', Object, {//Первый параметр — это имя класса. Если это строка, она будет автоматически зарегистрирована в classMap HT; второй параметр — родительский класс, который будет унаследован. этим классом ; Третий параметр — объявление методов и переменных addToDataModel: function(dm) { //Добавляем узел в контейнер данных dm.add(this._node); // Предопределенная функция в ht, передаем узел через добавление Метод добавлен в контейнер данных}, setHost: function() { //Установим адсорбцию this._node.setHost.apply(this._node, аргументы }, s3: function() {//Установим размер узла this._node .s3.apply(this._node, аргументы }, setElevation: функция()); {//Управляйте положением оси Y трехмерной системы координат, где находится центральное положение примитива Node this._node.setElevation.apply(this._node, аргументы }});
Создайте класс Editor.Server.
Этот класс может создать узел ht.Node и установить цвет и текстуру передней части узла:
var S = E.Server = function(obj) {//Компонент сервера var color = obj.color, frontImg = obj.frontImg; var node = this._node = new ht.Node();//Создаем узел node.s; ({//Установите для стиля узла аббревиатуру setStyle 'all.color': color,//Установите цвет шести сторон узла 'front.image': frontImg //Установим изображение в передней части узла});};
Таким образом, я могу напрямую создать новый объект серверного компонента, в котором мне нужно создать серверный компонент, и я могу напрямую вызвать setHost и другие объявленные выше функции, которые мы скоро будем использовать.
Затем создайте класс кабинета Editor.Cabinet. Этот метод аналогичен методу определения класса Editor.Server, приведенному выше:
ht.Default.def('Editor.Cabinet', Object, { addToDataModel: function(dm) { dm.add(this._door); dm.add(this._node); this._serverList.forEach(функция(ы) { s.addToDataModel(дм}); p3: функция() { this._node.p3.apply(this._node, аргументы);//Установим трехмерные координаты узла}});
Создать класс Editor.Cabinet
Этот класс относительно более сложен, чем предыдущий класс серверных компонентов Editor.Server. Этот класс создает корпус шкафа, дверцу шкафа и серверные компоненты внутри шкафа:
var C = E.Cabinet = function(obj) {var color = obj.color, DoorFrontImg = obj.doorFrontImg, DoorBackImg = obj.doorBackImg, s3 = obj.s3 = this._node = новый ht.Node(); ; // Кабинет node.s3(s3 //Установим размер узла setSize3d); node.a('cabinet', this);//Настройте свойства шкафа node.s({//Установите стиль узла на setStyle 'all.color': color,//Установите цвет шести сторон узла 'front.visible ': false//Установить, будет ли видна передняя часть узла}); if (Math.random() > 0.5) { node.addStyleIcon('alarm', {//Добавить имена значков к узлу: ['icon thermometer'], //Массив, содержащий несколько строк, каждая строка соответствует изображению или вектору (зарегистрированному через ht.Default.setImage) face: 'top', //Значение по умолчанию — спереди, значок Ориентация в 3D , доступные значения: left|right|top|bottom|front|back|center Position: 17, //Указываем положение значков автоповорота: 'y', //Значение по умолчанию — false, независимо от того, смотрит ли значок автоматически в направлении взгляда в 3D t3: [0, 16, 0], //Значение по умолчанию не определено, смещение значка в 3D, формат — [x,y,z] ширина: 37, //Укажите ширину каждого значка, значение по умолчанию основано на ширине при регистрации высоты изображения: 32, //Укажите высоту каждого значка, значение по умолчанию — на основе высоты при регистрации изображения в текстуреScale: 4, //Значение по умолчанию — 2. Это значение представляет собой кратное фактической карте, созданной памятью. Его не следует устанавливать слишком большим, иначе это повлияет на производительность. { func: function() { return !! E.alarmVisible; }}//Указывает, отображать ли группу изображений }); var Door = this._door = new. ht.DoorWindow();//Дверь шкафа Door.setWidth(s3[0]);//Установить длину графического элемента в направлении оси X в 3D-топологии Door.setHeight(1);//Установить графический элемент в 3D-топологии по оси Z Длина Door.setTall(s3[1]);//Управляйте длиной примитива Node по оси Y Door.setElevation(0);//Устанавливаем координату y центра примитива в 3D-системе координат Door .setY(s3[2 ] * 0.5);//Установим положение узла на оси Y Door.setHost(node);//Установим адсорбционную дверь.s({//Установим стиль узла setStyle 'all.color': color,/ /Установить цвет шести сторон узла 'front.image':doorFrontImg, //Установить переднее изображение узла 'front.transparent': true, //Установить, является ли передняя грань узла прозрачной 'back .image':doorBackImg, //Установим изображение на обратной стороне узла 'back.uv': [1,0, 1,1, 0,1, 0,0], // Настройте UV-карту за узлом. Если она пуста, значение по умолчанию [0,0, 0,1, 1,1, 1. ,0] 'dw.axis': 'right'//Установим ось вращения для операций расширения и закрытия элемента DoorWindow, возможные значения: left|right|top|bottom|v|h }); ._serverList = []; max = 6, list = E.randomList(max, Math.floor(Math.random() * (max - 2)) + 2); //Функция получения случайных чисел, объявленная в global.js var server, h = s3); [0] / 4; list.forEach(function(r) { var server = new E.Server({ //Цвет компонента сервера: 'rgb(51,49,49)', frontImg: 'Серверный компонент в порядке' }); server.s3(s3[0] - 2, h, s3[2] - 4);//Установим размер узла server.setElevation((r - max * 0.5) * (h + 2 ));//Установим координаты центра узла на оси Y server.setHost(node);//Установим адсорбцию узла serverList.push(server);//To serverList Добавьте узел сервера в });};
Единственное, что не упомянуто в приведенном выше коде, — это функция Editor.randomList. Эта функция объявлена в файле global.js и объявляется следующим образом:
var E = window.Editor = { leftWidth: 0, topHeight: 40, randomList: function(max, size) { var list = [], ran; while (list.length <size) { ran = Math.floor(Math. случайный() * Макс); если (list.indexOf(ran) >= 0) продолжить; list.push(ran); return list }};
Хорошо, теперь, когда классы для каждой части сцены созданы, нам следует создать сцену и затем сложить в нее эти примитивы!
Создание сценыСтуденты, знакомые с ним, должны знать, что для использования HT для создания 3D-сцены требуется только новый 3D-компонент, а затем добавить сцену в тело с помощью функции addToDOM:
var g3d = E.main = new ht.graph3d.Graph3dView(); //3D-сцена
Файл main.js в основном выполняет некоторые необходимые элементы в 3D-сцене, такие как стены, полы, двери, кондиционеры, а также положения генерации и разгрузки всех шкафов, а также очень важные интерактивные части.
Я не буду публиковать код создания стен, полов, дверей, кондиционеров и шкафов. Если вам интересно, пожалуйста, проверьте код самостоятельно. Здесь в основном речь идет о двойном щелчке по шкафу и любым объектам, связанным со шкафом (). двери шкафа, серверное оборудование) для создания 3D. Центр линии обзора камеры переместится в определенное положение перед шкафом при двойном щелчке, и это движение очень плавное. Раньше у меня это не получалось, поэтому я подумал. об этой части уже давно и, наконец, упомянул метод реализации этой демонстрации.
Чтобы иметь возможность неоднократно устанавливать глаз и центр, содержимое, соответствующее установке этих двух параметров, инкапсулируется в методы setEye и setCenter. Метод setCenter аналогичен методу setEye и не будет здесь повторяться:
//Установим положение глаза var setEye = function(eye, Finish) { if (!eye) return; - e[0], dy = Eye[1] - e[1], dz = Eye[2] - e[2] // Запускаем переход анимации длительностью 500 миллисекунд ht.Default.startAnim({ длительность: 500, easing: easing,//Функция замедления анимации FinishFunc: Finish || function() {}, //Функция, вызываемая после завершения анимации action: function(v, t) {//Устанавливаем анимацию v для представления проходящего замедления (t) Значение после операции функции, t представляет ход текущей анимации [0~1], общие изменения атрибутов основаны на параметре v g3d.setEye([ //Установка глаза в 3D-сцене Значение глаза представляет собой массив, соответствующий значениям осей x, y и z соответственно e[0] + dx * v, e[1] + dy * v, e[2] + dz * v ]); } }) ;};
То, что я неоднократно не объявлял функцию setCenter, не означает, что эта функция не важна. Наоборот, эта функция играет решающую роль в процессе перемещения линии взгляда. Вышеописанная функция setEye эквивалентна моему желанию. идти перед моей целевой позицией (по крайней мере, я определяю, что для этой цели используется), в то время как sCenter Определение состоит в том, чтобы переместить мой прицел в положение цели (например, я могу стоять в своем текущем положении и смотреть на объект позади меня справа, или я могу пойти назад, справа от меня, и встать перед объектом). объект, чтобы посмотреть на него). Это очень важно, пожалуйста, наслаждайтесь им.
Событие двойного щелчка простое. Просто прослушайте событие, инкапсулированное HT, определите тип события и выполните соответствующие действия:
g3d.mi(function(e) {//addInteractorListener функция прослушивания событий if (e.kind !== 'doubleClickData') //Определяем тип события как возврат узла по двойному щелчку; var data = e.data, p3 ; if (data. a('cabinet')) //Body p3 = data.p3(); else {host = data.getHost(); //Получаем объект адсорбции выбранного узла if (host && host.a('cabinet')) {//Если объектом адсорбции является шкаф p3 = host.p3(); } } if (!p3) return; setCenter(p3); //Устанавливаем положение перемещения центральной цели равным The. позиция шкафа setEye([p3[0], 211, p3[2] + 247] //Установим позицию, куда будет двигаться глаз});верхняя панель навигации
Когда я впервые увидел этот пример, я подумал: этот человек такой потрясающий. Я так долго использую HT, но мне до сих пор не удавалось создавать такие красивые эффекты с помощью ht.widget.Toolbar HT. Когда я посмотрел. при этом я понял, что на самом деле это было сделано с помощью HT. Это сделано с формой, это потрясающе, я такой глупый.
вар форма = E.top = новый ht.widget.FormPane(); //Компонент верхней формы form.setRowHeight(E.topHeight);//Установим высоту строки form.setVGap(-E.topHeight);//Установим горизонтальное расстояние компонента формы на отрицательное значение высоты строки, чтобы сохранить несколько строк в одной позиции Line form.setVPadding(0);//Установим верхнюю часть формы и расстояние между верхним краем и содержимым компонента form.addRow([null, {//Добавьте в форму строку компонентов. Первый параметр — это массив элементов. Элементами могут быть строки, информация о параметрах компонента, описанная в формате json, элементы HTML или нулевое изображение: { icon: './symbols/. inputBG.json ', растянуть: 'centerUniform' }}], [40, 260]);//Второй параметр представляет собой массив информации о ширине для каждого элемента. Значение ширины больше 1 представляет фиксированное абсолютное значение, а значение ширины меньше или равное 1 представляет собой относительное значение. комбинация 80+0,3 form.addRow([null, null, { id: 'searchInput', textField: {}}, { element: 'Система визуального управления компьютерным залом', цвет: 'white', шрифт: '18px arial , без засечек'}, ноль, { button: { // метка: 'ViewChange', значок: './symbols/viewChange.json', фон: null, selectBackground: 'rgb(128,128,128)', borderColor: 'rgba(0, 0, 0, 0) ', onClicked: function() { E.focusTo() } }}, null, { button: { // метка: 'Alert', значок: './symbols/alarm.json', переключаемый: true, выбранный: false, фон: ноль, selectBackground: 'rgb(128,128,128)', borderColor: 'rgba(0, 0, 0, 0)', onClicked: function( д) { E.setAlarmVisible(this.isSelected() } }}, null], [40, 42, 218, 300, 0,1, 50, 10, 50, 10]);
Вышеупомянутое только возможно, но оно фактически не добавляется в тег html, а это значит, что в интерфейсе теперь ничего нет! Не забудьте добавить 3D-сцену в тело при загрузке страницы и не забудьте добавить в тело форму. При настройке события изменения размера окна форма также должна обновляться в реальном времени:
window.addEventListener('load', function() { g3d.addToDOM(); //Добавляем 3D-сцену в тело document.body.appendChild(E.top.getView()); //Добавляем базовый элемент div Компонент формы Добавить в тело window.addEventListener('resize', function() {//Прослушивать события изменения размера окна E.top.iv();//Обновить базовый элемент div формы });});
Вот объяснение функции addToDOM, которая очень важна для понимания механизма HT. Компоненты HT обычно встраиваются в контейнеры, такие как BorderPane, SplitView и TabView. Самый внешний компонент HT требует, чтобы пользователь вручную добавил базовый элемент div, возвращаемый getView(), в элемент DOM страницы. Здесь необходимо отметить, что. , При изменении размера родительского контейнера, если родительским контейнером являются предопределенные компоненты контейнера HT, такие как BorderPane и SplitView, контейнер HT автоматически рекурсивно вызывает функцию недействительности дочернего компонента, чтобы уведомить об обновлении. Но если родительский контейнер является собственным элементом HTML, компонент HT не может знать, что его необходимо обновить. Поэтому самый внешний компонент HT обычно должен прослушивать событие изменения размера окна и вызывать функцию недействительности самого внешнего. компонент для обновления.
Чтобы облегчить загрузку самого внешнего компонента для заполнения окна, все компоненты HT имеют функцию addToDOM, логика ее реализации следующая, где iv — это сокращение от инвалидации:
addToDOM = function(){ var self = this, view = self.getView(), style = view.style; document.body.appendChild(view); //Добавляем базовый элемент div сцены в тело style.left = ' 0';//HT устанавливает абсолютное положение базового элемента div всех компонентов style.right = '0'; style.top = '0'; style.bottom = '0'; window.addEventListener('resize', function () { self.iv(); }, false //Прослушиваем события изменения размера окна и уведомляем об изменениях и обновлениях компонентов}
На этом весь код закончен. Вы можете щелкнуть правой кнопкой мыши, чтобы проверить его самостоятельно, и получить соответствующий json-файл из сети.
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.