🇷🇺
MyWebAR Knowledge Base
Язык Ру
Язык Ру
  • База знаний для разработчиков MyWebAR
  • С ЧЕГО НАЧАТЬ
    • Регистрация
    • Обзор страницы Dashboard
    • Обзор редактора
    • Создание проекта в MyWebAR
  • ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ MYWEBAR
    • Создание сцены с трекингом на изогнутых изображениях
    • Создание AR-визитки
    • Создание портала в MyWebAR
    • Оживающая фотография
    • Интерактив с 3D-моделью
  • ПЛАНЫ И ПОДПИСКИ
    • Бесплатная пробная подписка
    • Обновление вашего плана
    • Коммерческие планы
    • Планы для образования
  • СОЗДАНИЕ ПРОЕКТОВ WEBAR
    • Типы проектов
    • Проекты с мультимаркерным трекингом (книги)
    • Добавление объектов
    • Как добавить 3D-модель из библиотеки моделей
    • Как добавить 3D-модель из Sketchfab
    • Свойства объекта
    • Кнопки и действия
    • Поведения объектов
    • Воспроизведение видео
    • 3D Анимации
    • Аналитика проектов
    • Как сделать хорошее отслеживаемое изображение для дополненной реальности
    • Оптимизация и подготовка 3D-моделей к загрузке
    • Брендирование проекта и его настройки
    • Работа с доступными плагинами
    • Существующие плагины и как с ними работать
    • Видео инструкции
  • КАСТОМИЗАЦИЯ WEBAR
    • Кастомный домен
    • Использование внешнего хранилища
    • Встраивание WebAR
  • Pro Editor
    • Как устроен Pro Editor
      • Описание интерфейса
      • Основные возможности
    • Требования по размещению кода
      • Пример интеграции готового скрипта
      • Создание частиц в Pro Editor
      • Работа с видео
      • Работа с анимациями 3D-объектов
    • Текущие ограничения
      • Работа с камерой
      • Создание UI
      • Загрузка объектов с помощью класса loader
      • Импорт частей кода
    • Кейсы
      • Добавление изображений
      • Эффект бликов на объективе (Lens Flare)
      • Пошаговое создание мини-игры
      • Переключение содержимого по нажатию
      • Пошаговое создание квеста
Powered by GitBook
On this page
  • Проблема
  • Рабочий способ
  1. Pro Editor
  2. Текущие ограничения

Создание UI

PreviousРабота с камеройNextЗагрузка объектов с помощью класса loader

Last updated 2 years ago

Проблема

Очень часто может потребоваться создание какого-либо интерфейса для прямого взаимодействия с пользователем. Обычно, в игровых движках, таких как Unity, Unreal Engine и так далее, интерфейс создается в пару кнопок.

Раньше же, интерфейс создавали другим способом — создавали текстурированную плоскость (UI) и выносили её куда-то вдаль. Далее, создавали еще одну камеру, которая проецировала этот интерфейс уже на экран пользователя.

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

На данный момент, единственным способом добавления UI, является работа с HTML-кодом страницы. Но этот вариант не будет являться правильным, так как это может плохо сказаться на работе сцены в дополненной реальности.

Рабочий способ

В данном случае я создам 2D-кнопку для воспроизведения анимации 3D-модели. Вы можете посмотреть результат, отсканировав QR-код ниже.

Для создания интерфейса первым делом необходимо создать пустой проект.

Далее необходимо добавить 3D-объект, нажав на кнопку File → Import.

Этот объект должен содержать как минимум одну анимацию.

Теперь выберите объект Scene в дереве объектов справа.

Чтобы создать сценарий, нажмите на кнопку NEW.

Далее необходимо перейти в редактор кода, нажав на кнопку Edit.

Теперь можно приступить непосредственно к написанию кода.

Первое, что нужно сделать, это создать функцию для создания интерфейса, назвав ее makeUI().

function makeUI() {
    
}

После этого необходимо создать новый HTML-элемент <div>, который будет являться контейнером (строки 2-5).

let container;
function makeUI() {
	container = document.createElement('div');
	container.id = 'container';
	container.style.display = 'none';
	document.body.appendChild(container);
}

Чтобы избежать создания нового элемента <div> при каждом запуске сцены, следует добавить проверку существования контейнера с помощью if (строки 2-3).

let container;
function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		document.body.appendChild(container);
	}
}

Далее необходимо добавить элемент <img> внутри контейнера, который будет 2D-интерфейсом (строки 10-14).

let container;
function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		document.body.appendChild(container);
	}
	const img = document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	img.style.display = 'block';
	container.appendChild(img);
}

Давайте немного изменим строку 9 (создание элемента), добавив проверку на его существование, чтобы элемент не был клонирован.

let container;
function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		document.body.appendChild(container);
	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	img.style.display = 'block';
	container.appendChild(img);
}

Далее нам нужно добавить стили к этим элементам, чтобы изображение находилось точно в нижней части экрана. Для этого я создам объект styles вне этой функции (строки 2-17). После этого я привяжу стили к контейнеру и изображению (строки 25 и 32).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

Далее необходимо создать три функции: init, start и stop. Это три функции js, которые выполняются при инициализации сцены (init), запуске сцены (start) и остановке сцены (stop).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

function init() {
	
}
function start() {

}
function stop() {
	
}

В функциях init и start необходимо вызвать makeUI() для его запуска. В этом случае интерфейс появится сразу при запуске сцены (строки 38 и 43).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

function init() {
	makeUI();
}
function start() {
	makeUI();
}
function stop() {

}

Теперь необходимо сделать так, чтобы интерфейс скрывался и появлялся. Для этого измените свойство контейнера container.style.display (строки 42 и 46) в функциях start (появляться) и stop (скрываться).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

function init() {
	makeUI();
}
function start() {
	makeUI();
	container.style.display = 'block';
}
function stop() {
	container.style.display = 'none';
}

Теперь необходимо создать событие щелчка для добавленного интерфейса. Событие создается с помощью чистого JavaScript. Для этого создайте функцию clickFunction (строки 37-40), которая будет запускаться при нажатии на изображение. Также в функцию запуска нужно добавить слушателя события (строка 48).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

function clickFunction() {
	container.style.display = 'none';
}

function init() {
	makeUI();
}
function start() {
	makeUI();
	container.style.display = 'block';
	container.addEventListener("click", clickFunction);
}
function stop() {
	container.style.display = 'none';
}

Последний шаг - работа с анимацией. Подробнее о работе с анимацией в PRO EDITOR вы можете прочитать в статьеРабота с анимациями 3D-объектов. В данном случае был добавлен один анимационный ролик (строки 37-46). Сама анимация должна быть запущена внутри функции события clickFunction (строка 49).

let container;
const styles = {
	container: {
		position: 'absolute',
		zIndex: 9999,
		left: '0',
		right: '0',
		bottom: '0',
		marginLeft: 'auto', 
		marginRight: 'auto', 
		width: '120px',
	},
	img: {
		height: '120px',
		width: '120px',
	},
};

function makeUI() {
	container = document.getElementById('container');
	if (!container) {
		container = document.createElement('div');
		container.id = 'container';
		container.style.display = 'none';
		Object.assign(container.style, styles.container);
		document.body.appendChild(container);

	}
	const img = container.querySelector('#imageButton')||  document.createElement('img');
	img.src = 'https://mywebar-a.akamaihd.net/15103/play-button-arrows-svgrepo-com.png';
	img.id='imageButton'
	Object.assign(img.style, styles.img);
	img.style.display = 'block';
	container.appendChild(img);
}

let clock = new THREE.Clock();
const myObject = scene.getObjectByName('stegosaurus_rigcharacter');
const clip = myObject.animations[0];
const mixer = new THREE.AnimationMixer(myObject);
const action = mixer.clipAction(clip);
function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
}

function clickFunction() {
	action.play();
	container.style.display = 'none';
}

function init() {
	makeUI();
}
function start() {
	makeUI();
	container.style.display = 'block';
	container.addEventListener("click", clickFunction);
}
function stop() {
	container.style.display = 'none';
}

Сцена готова. Теперь нужно экспортировать сцену в MyWebAR, нажав File → Publish.

Вернитесь в стандартный редактор, нажмите на тип объекта Json MAE на левой панели и загрузите файл .json, который вы экспортировали из продвинутого редактора.

На сцене появится 3D-объект. Сам интерфейс будет виден только в предварительном просмотре или в дополненной реальности.