# Создание UI

## Проблема

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FMnqJtZG5t5fC7aJjX8R1%2Fimage.png?alt=media\&token=377f87f3-9365-45bd-95f9-969e9f31a79e)

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

К сожалению, данный способ не может быть воссоздан в продвинутом редакторе. Про ограничения о работе с камерами было описано в статье [rabota-s-kameroi](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/pro-editor/tekushie-ogranicheniya/rabota-s-kameroi "mention").

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

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

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FJK7NySIb2sFXBOmdOlwD%2Fimage.png?alt=media\&token=a97c9327-7bde-46bd-96da-c88d59e80982)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FLOj0IdoOIH5Ksb7hgQMN%2Fimage.png?alt=media\&token=086ded8e-c648-4277-9cc8-821dcf46eacc)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FdNUd2rcC0KnTPz8D6tqR%2FInterface_1.png?alt=media\&token=1317688f-9b9d-4600-abc2-731d6bfc717e)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FpL8V0EjmQS0j6hfllrNQ%2Fimage.png?alt=media\&token=b04d6beb-c6d4-49c3-bdc3-cbd109952e12)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2F219oFqt4WVhgWq3uePHJ%2FInterface_2.jpg?alt=media\&token=4469b978-5e66-42e3-ad40-3124463edc3c)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FC7xfabgNLLUjoj9U5btq%2FInterface_3.jpg?alt=media\&token=9e3603da-bac3-41b2-9cb2-c2a672afbf6f)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FBdfPr6Z3P595JyqfjMZK%2FInterface_4.jpg?alt=media\&token=046248be-fc20-4ea7-bb9d-2240019ce25d)

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

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

{% code lineNumbers="true" %}

```javascript
function makeUI() {
    
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

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

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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);
	}
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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);
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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);
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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);
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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() {
	
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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() {

}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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';
}
```

{% endcode %}

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

{% code lineNumbers="true" %}

```javascript
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';
}
```

{% endcode %}

Последний шаг - работа с анимацией. Подробнее о работе с анимацией в PRO EDITOR вы можете прочитать в статье[rabota-s-animaciyami-3d-obektov](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/pro-editor/trebovaniya-po-razmesheniyu-koda/rabota-s-animaciyami-3d-obektov "mention"). В данном случае был добавлен один анимационный ролик *(строки 37-46)*. Сама анимация должна быть запущена внутри функции события `clickFunction` *(строка 49)*.

{% code lineNumbers="true" %}

```javascript
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';
}
```

{% endcode %}

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FQ2yGkLvGfLG367HAJltd%2FInterface_5.jpg?alt=media\&token=50c00240-95ec-4022-9d1b-056ef0461311)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2F2WDtIp7zWCeOBzsOhYD2%2FInterface_6.jpg?alt=media\&token=4e1c2c4c-f442-4e28-b997-c2329eb17621)

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

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FK1JYIJmdcRHjcMMkTUqc%2Fimage.png?alt=media\&token=137bca9a-77f7-4f29-ad00-254a2b98ab03)
