Перейти к содержимому

Ui скрипты что это

  • автор:

GUI-скриптинг

Для управления логикой GUI и анимацией нод используются Lua-скрипты. GUI-скрипты работают так же, как и обычные скрипты игровых объектов, но сохраняются как файл другого типа и имеют доступ к другому набору функций: функциям модуля gui .

Добавление скрипта в GUI

Чтобы добавить скрипт в GUI, сперва создайте файл GUI-скрипта, кликнув ПКМ в каком-либо расположении в браузере Assets и выбрав New ▸ Gui Script и выпадающего контекстного меню.

Редактор автоматически открывает новый файл скрипта. Он основан на шаблоне и оснащен пустыми функциями времени жизни, как и скрипты игровых объектов:

function init(self) -- Добавьте здесь код инициализации -- Удалите эту функцию, если она не нужна end function final(self) -- Добавьте здесь код инициализации -- Удалите эту функцию, если она не нужна end function update(self, dt) -- Добавьте здесь код обновления -- Удалите эту функцию, если она не нужна end function on_message(self, message_id, message, sender) -- Добавьте сюда код обработки сообщений -- Удалите эту функцию, если она не нужна end function on_input(self, action_id, action) -- Добавьте сюда код обработки ввода -- Удалите эту функцию, если она не нужна end function on_reload(self) -- Добавьте сюда код обработки ввода -- Удалите эту функцию, если она не нужна end 

Чтобы прикрепить скрипт к компоненту GUI, откройте файл компонента GUI и выделите его корень в Outline, чтобы вызвать свойства GUI. Задайте свойству Script требуемый файл скрипта.

Script

Если компонент GUI был добавлен к игровому объекту где-либо в игре, скрипт будет запущен.

Пространство имен в “gui”

GUI-скрипты имеют доступ к пространству имен gui и всем gui-функциям. Пространство имен go недоступно, поэтому необходимо отделить логику игрового объекта в компоненты Script и осуществлять связь между GUI и скриптами игрового объекта. Любая попытка использовать функции go приведет к ошибке:

function init(self) local id = go.get_id() end 
ERROR:SCRIPT: /main/my_gui.gui_script:2: You can only access go.* functions and values from a script instance (.script file) stack traceback: [C]: in function 'get_id' /main/my_gui.gui_script:2: in function

Передача сообщений

Любой компонент GUI с подключенным скриптом может взаимодействовать с другими объектами в рантайме игры посредством передачи сообщений, он будет вести себя как любой другой скриптовый компонент.

Обращение к компоненту GUI происходит так же, как и к любому другому компоненту скрипта:

local stats =  score = 4711, stars = 3, health = 6 > msg.post("hud#gui", "set_stats", stats) 

message passing

Обращение к нодам

GUI-нодами можно манипулировать с помощью GUI-скрипта, прикрепленного к компоненту. Каждая нода должна иметь уникальный Id, который задается в редакторе:

message passing

Id позволяет скрипту получить ссылку на ноду и манипулировать ею с помощью функций пространства имен gui:

-- расширить полосу здоровья на 10 единиц local healthbar_node = gui.get_node("healthbar") local size = gui.get_size(healthbar_node) size.x = size.x + 10 gui.set_size(healthbar_node, size) 

Динамически создаваемые ноды

Чтобы создать новую ноду со скриптом в рантайме, есть два варианта. Первый вариант — создавать ноды с нуля, вызвав функции gui.new_[type]_node() . Они вернут ссылку на новую ноду, которую можно использовать для манипуляций с нодой:

-- Создать новую ноду Box local new_position = vmath.vector3(400, 300, 0) local new_size = vmath.vector3(450, 400, 0) local new_boxnode = gui.new_box_node(new_position, new_size) gui.set_color(new_boxnode, vmath.vector4(0.2, 0.26, 0.32, 1)) -- Создать новую ноду Text local new_textnode = gui.new_text_node(new_position, "Hello!") gui.set_font(new_textnode, "sourcesans") gui.set_color(new_textnode, vmath.vector4(0.69, 0.6, 0.8, 1.0)) 

dynamic node

Альтернативным способом создания новых нод является клонирование существующей ноды с помощью функции gui.clone() или дерева нод с помощью функции gui.clone_tree() :

-- клонировать полосу здоровья local healthbar_node = gui.get_node("healthbar") local healthbar_node_2 = gui.clone(healthbar_node) -- кнопка клонирования дерева нод local button = gui.get_node("my_button") local new_button_nodes = gui.clone_tree(button) -- получить новый корень дерева local new_root = new_button_nodes["my_button"] -- переместить корень (и дочерние элементы) на 300 вправо local root_position = gui.get_position(new_root) root_position.x = root_position.x + 300 gui.set_position(new_root, root_position) 

Id динамических узлов

Динамически созданные ноды не имеют присвоенного им идентификатора. Это сделано специально. Ссылки, возвращаемые из gui.new_[type]_node() , gui.clone() и gui.clone_tree() — это единственное, что необходимо для доступа к нодам, поэтому необходимо отслеживать эти ссылки.

-- Добавить ноду Text local new_textnode = gui.new_text_node(vmath.vector3(100, 100, 0), "Hello!") -- "new_textnode" содержит ссылку на ноду. -- Нода не имеет идентификатора, и это нормально. -- Нет причин выполнять gui.get_node(), когда у нас уже есть ссылка. 

Did you spot an error or do you have a suggestion? Please let us know on GitHub!

Что такое script в HTML5?

HTML тег .

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

Вы можете использовать тег

Атрибуты:

Пример:

       

Использование библиотеки jQuery UI на практике

Библиотека jQuery UI состоит из виджетов и взаимодействий, которые позволяют создавать насыщенные веб-приложения со стилевым оформлением пользовательского интерфейса, подчиняющимся определенной теме, и обеспечивают чрезвычайно гибкие возможности настройки в соответствии с конкретными задачами. Ранее мы рассмотрели все эти виджеты и взаимодействия и в этой статье некоторые из указанных средств будут добавлены в наш базовый пример для демонстрации того, каким образом можно организовать их совместную работу.

В качестве отправной точки для данной статьи мы используем вариант документа, приведенный в примере ниже:

    jQuery UI         

Цветочный магазин

В этом документе необходимые элементы генерируются с помощью шаблона данных (для сокращения разметки документа) на основании информации о продуктах, извлекаемой из файла JSON с помощью метода getJSON(). Вся совокупность элементов, соответствующих отдельным видам продукции, собирается в единственном элементе с идентификатором products. Файл mydata.json находиться в одном каталоге с документом и содержит следующие данные:

Также не забудьте добавить файл таблицы стилей styles.css:

h1 < min-width: 70px; border: thick double black; margin-left: auto; margin-right: auto; text-align: center; font-size: x-large; padding: .5em; color: darkgreen; margin-top: 0; >.dtable .drow .dcell .dcell > * input label #buttonDiv #oblock

Вид исходного документа в окне браузера представлен на рисунке:

Исходный документ для примеров

Отображение данных

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

. $(function() < $.getJSON("mydata.json", function(data) < var flowers = $('#flowerTmpl').tmpl(data); var rowCount = 1; for (var i = 0; i < flowers.length; i += 2) < $("

" + data[i].name + " и " + data[i + 1].name.toLowerCase() + "

").appendTo("#products"); $(" ") .appendTo("#products") .append(flowers.slice(i, i + 2)) > $('#products').accordion(); >); >); .

Здесь в функцию, передаваемую методу getJSON(), добавлен код, предназначенный для создания виджета Accordion, включая построение необходимой структуры элементов и вызов метода accordion(). В новой реализации названия цветов извлекаются из соответствующего источника с помощью объекта данных JSON, но для генерации HTML-элементов (которые затем разбиваются на группы и помещаются в оболочки, образуемые элементами div, в соответствии с требованиями виджета Accordion) по-прежнему используется подключаемый модуль шаблонов данных.

Вид документа в окне браузера после добавления вызова метода accordion() представлен на рисунке:

Создание структуры элементов и вызов метода accordion()

Добавление корзины покупателя

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

Запустить пример    jQuery UI      .dcell img #basketTable th, td td:first-child, th:first-child #placeholder #productWrapper #basket #buttonDiv     

Цветочный магазин

ПродуктКоличествоУдалить
Ничего не выбрано

Давайте рассмотрим этот код более подробно.

Помещение виджета Accordion в оболочку

Мы хотим, чтобы корзина покупателя отображалась рядом с панелями виджета Accordion. Для этого мы помещаем элемент, для которого вызывается метод accordion(), внутрь другого элемента div:

Работа виджета Accordion будет нарушена, если окажется, что он не занимает все пространство родительского элемента по ширине, поэтому мы добавляем оболочку и фиксируем ее ширину с помощью CSS-свойства width:

#productWrapper

Таким образом, виджет Accordion, как и должно быть, благополучно располагается по всей ширине элемента-оболочки div, который занимает только 65% ширины своего родительского элемента.

Добавление таблицы

Для отображения корзины мы используем элемент table, который включаем в число статических элементов документа:

 
ПродуктКоличествоУдалить
Ничего не выбрано

Как и в случае виджета Accordion, мы помещаем элемент table в оболочку, ширину которой устанавливаем с помощью CSS-свойства:

#basket

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

Обработка изменений входных значений

Чтобы связать таблицу с виджетом Accordion, мы реагируем на события change, порождаемые элементами input, которые создаются в функции getJSON(). Это делается с помощью следующей функции-обработчика:

$('input').change(function(event) < $('#placeholder').hide(); var fname = $(this).attr("name"); var row = $('tr[id=' + fname + ']'); if (row.length == 0) < $('#rowTmpl').tmpl(< name: fname, val: $(this).val(), product: $(this).siblings("label").text() >).appendTo("#basketTable").find("a").click(function() < removeTableRow($(this).closest("tr")); var iElem = $('#products').find("input[name=" + fname + "]") $('#products').accordion("activate", iElem.closest("div[id^=row]").prev()) iElem.val(0).select(); >) > else if ($(this).val() != "0") < row.children().eq(1).text($(this).val()) >else < removeTableRow(row) >>)

Эта функция-обработчик решает множество задач. Прежде всего, когда пользователь изменяет какое-либо значение, осуществляется проверка того, имеется ли уже в таблице строка, соответствующая данному продукту. В случае отсутствия такой строки создается новая строка, для генерации которой используется шаблон:

Необходимые для данного шаблона значения получаются с помощью методов ядра jQuery, которые извлекают информацию из элемента input, породившего событие. Мы хотим отображать также названия продуктов, и с этой целью выполняем поиск в DOM-дереве для нахождения ближайшего элемента label и считывания его содержимого:

$(this).siblings("label").text()

Вновь созданная строка присоединяется к таблице. Ряд-заполнитель был скрыт еще раньше в самом начале выполнения функции-обработчика:

$('#placeholder').hide();

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

Добавление строк в таблицу корзины

Удаление строк

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

. .appendTo("#basketTable").find("a").click(function() < removeTableRow($(this).closest("tr")); var iElem = $('#products').find("input[name=" + fname + "]") $('#products').accordion("option", "active", Number(iElem.closest("div[id^=row]").attr('id').substring(3)) - 1) iElem.val(0).select(); >) . 
function removeTableRow(row) < row.remove(); if ($('#basketTable tbody').children(':visible').length == 1) < $('#placeholder').show(); >>

Удалив строку из таблицы корзины покупателя, мы находим среди продуктов элемент input, связанный с данной строкой. Затем мы используем навигацию по DOM-дереву для поиска элемента, являющегося ближайшим предшествующим сестринским элементом по отношению к элементу div, который содержит данный элемент input, и передаем его индекс свойству active виджета Accordion. Это приводит к раскрытию той части виджета Accordion, которая содержит элемент, только что удаленный пользователем из корзины.

Наконец, мы устанавливаем значение данного элемента input равным 0 и вызываем метод select(), в результате чего этот элемент получает фокус ввода, а содержащееся в нем значение выделяется.

Обновление существующих строк

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

row.children().eq(1).text($(this).val())

Переменная row — это объект jQuery, содержащий элемент tr для продукта в таблице. Доступ к элементу td осуществляется по номеру позиции (с помощью метода eq()), а его содержимое устанавливается с помощью метода text().

Применение темы оформления

Теперь наша корзина функционирует вполне удовлетворительно, но ее внешний вид оставляет желать лучшего. К счастью, jQuery UI предоставляет библиотеку CSS-стилей (CSS-фреймворк), которые можно применить к элементам, чтобы они выглядели так же, как и виджеты после применения к ним выбранной вами темы стилевого оформления. В примере ниже показано, насколько просто получить требуемый результат путем добавления классов в HTML-элементы документа:

. 
class="ui-widget ui-widget-content"> class="ui-widget-header">
ПродуктКоличествоУдалить
Ничего не выбрано
.

Для элемента table дополнительно к использованию указанных классов задано отсутствие границ (рамки):

#basketTable

Полученный результат проиллюстрирован на рисунке:

Создание кнопки jQuery UI

Наш следующий шаг — перемещение кнопки в другое место и ее преобразование в виджет jQuery UI. Для этого внесем изменения в функцию-обработчик загрузки страницы:

$(function() < . $('#buttonDiv, #basket').wrapAll("").parent().css(< float: "left", marginLeft: "2px" >) $('button').button() >);

а также добавим пару CSS-стилей:

#basket #buttonDiv

Здесь мы поместили элементы buttonDiv и basket в новый элемент div и изменили некоторые CSS-стили для настройки позиций этих элементов. И наконец, мы вызываем метод button() для создания кнопки jQuery UI, как показано на рисунке:

Перемещение и преобразование элемента button

Добавление диалогового окна для завершения заказа

Мы хотим, чтобы, прежде чем завершить оформление заказа, щелкнув на кнопке «Заказать», пользователь предоставил нам некоторую дополнительную информацию о себе. Чтобы внести некоторое разнообразие, воспользуемся виджетом Dialog. Также добавим функцию обработки введенных пользователем данных. В примере ниже показан конечный код примера, а затем мы более подробно рассмотрим нововведения:

Запустить пример    jQuery UI      .dcell img #basketTable th, td td:first-child, th:first-child #placeholder #productWrapper #buttonDiv #basketTable #basket #buttonDiv /* 2 новых стиля */ #completeDialog input #completeDialog label     

Цветочный магазин

ПродуктКоличествоУдалить
Ничего не выбрано

Здесь мы добавили элемент div, содержимое которого будет отображаться для пользователя в элементе body, а также некоторые CSS-стили, заменяющие стили из файла styles.css, которые импортируются в документ с помощью элемента link. Для создания диалогового окна используется следующий вызов метода dialog():

$('#completeDialog').dialog(< modal: true, autoOpen: false, buttons: [, >] >);

Здесь мы создаем модальный вариант диалогового окна, в котором есть две кнопки. После щелчка на кнопке «Отмена» диалоговое окно закрывается. Щелчок на кнопке «OK» приводит к вызову функции sendOrder():

function sendOrder() < var data = new Object(); $('input').each(function(index, elem) < var jqElem = $(elem); data[jqElem.attr("name")] = jqElem.val(); >) console.log(JSON.stringify(data)); $('#completeDialog').dialog("close"); $('#products input').val("0"); $('#products').accordion("option", "active", 0) $('#basketTable tr').has(':not(th)').filter(':visible').remove(); $('#placeholder').show(); >

В этой функции мы получаем значения, содержащиеся в каждом из текстовых полей, и добавляем их в виде свойств в объект, который затем преобразуем в формат JSON и выводим на консоль.

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

Предоставление дополнительной информации для завершения оформления заказа

Щелчок на кнопке «OK» приводит к генерации данных в формате JSON и восстановлению исходного состояния документа. Консольный вывод имеет следующий вид:

Консольный вывод заказа

Когда пользователь щелкает на кнопке, мы проверяем, является ли элемент placeholder видимым. Это делается с помощью селектора jQuery, предоставляющего объект, который содержит элементы лишь в том случае, если указанный элемент виден на экране.

Здесь видимость элемента placeholder используется для индикации того, выбран ли пользователем хотя бы один продукт. Если в корзине покупателя есть хотя бы один продукт, этот элемент скрыт, и его появление говорит о том, что ни один продукт выбран не был:

$('#buttonDiv button').button().click(function(e) < e.preventDefault(); if ($('#placeholder:visible').length) < $('
Вы ничего не выбрали для заказа
').dialog(< modal: true, buttons: [>] >) > else < $('#completeDialog').dialog("open"); >>)

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

Если пользователь выполняет щелчок на кнопке, не выбрав ни одного продукта, динамически создается и отображается диалоговое окно, представленное на рисунке ниже:

Диалоговое окно, напоминающее о необходимости выбрать продукт

В этой статье мы переработали простой документ, включив в него интерактивные возможности, предлагаемые библиотекой jQuery UI. В него были добавлены виджеты Accordion, Dialog и Button, а также использовалась функциональность классов CSS-фреймворка jQuery UI для управления внешним видом других элементов.

Веб-компонент в сборе

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/web-components.

В этой главе мы посмотрим на итоговый пример веб-компонента, включающий в себя описанные ранее технологии: Custom Elements, Shadow DOM, CSS Scoping и, конечно же, Imports.

Компонент ui-message

Компонент ui-message будет описан в отдельном файле ui-message.html .

Его использование будет выглядеть следующим образом:

  ui-message 

Этот код ничем не отличается от использования обычного элемента, поэтому перейдём дальше, к содержимому ui-message.html

Шаблон для ui-message

Файл ui-message.html можно начать с шаблона:

 

Этот шаблон рисует и заполняет его содержимым элемента-хозяина.

Скрипт для ui-message

В файле ui-message.html мы создадим новый элемент :

// (1) получить шаблон var localDocument = document.currentScript.ownerDocument; var tmpl = localDocument.getElementById('tmpl'); // (2) создать элемент var MessageProto = Object.create(HTMLElement.prototype); MessageProto.createdCallback = function() < var root = this.createShadowRoot(); root.appendChild(tmpl.content.cloneNode(true)); >; // (3) зарегистрировать в DOM document.registerElement('ui-message', < prototype: MessageProto >);

Все компоненты этого кода мы подробно разбирали ранее:

  1. Получаем шаблон из текущего документа, то есть из самого импорта.
  2. Описываем элемент. Он довольно прост – при создании записывает в свой Shadow DOM шаблон. При этом содержимое исходного элемента будет показано в , но делать правила на сам content бессмысленно – они не сработают. Нужно либо перейти внутрь при помощи ::content -селектора, либо указать для внешнего элемента .content , что в данном случае и сделано.
  3. С момента регистрации все уже существующие элементы будут превращены в описанные здесь. И будущие, конечно, тоже.

Компонент в действии:

ui-message.html

      ui-message    
       

Компонент ui-slider с jQuery

Компонент может использовать и внешние библиотеки.

Для примера создадим слайдер с использованием библиотеки jQuery UI.

Компонент ui-slider будет показывать слайдер с минимальным и максимальным значением из атрибутов min/max и генерировать событие slide при его перемещении.

Файл компонента ui-slider

Файл ui-slider.html , задающий компонент, мы разберём по частям.

Заголовок

В начале подключим jQuery и jQuery UI.

Мы импортируем в слайдер jquery.html , который содержит теги вместо того, чтобы явным образом прописывать загрузку скриптов:

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

То есть, это средство оптимизации.

Шаблон

Шаблон будет помещён в Shadow DOM. В нём должны быть стили и элементы, необходимые слайдеру.

Конкретно для слайдера из разметки достаточно одного элемента , который затем будет обработан jQuery UI.

Кроме того, в шаблоне должны быть стили:

 @import url(https://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css); :host 

Скрипт

Скрипт для нового элемента похож на тот, что делали раньше, но теперь он использует jQuery UI для создания слайдера внутри своего Shadow DOM.

Для его понимания желательно знать jQuery, хотя в коде ниже я намеренно свёл использование этой библиотеки к минимуму.

var localDocument = document.currentScript.ownerDocument; var tmpl = localDocument.getElementById('tmpl'); var SliderProto = Object.create(HTMLElement.prototype); SliderProto.createdCallback = function() < // (1) инициализировать Shadow DOM, получить из него #slider var root = this.createShadowRoot(); root.appendChild(tmpl.content.cloneNode(true)); this.$slider = $(root.getElementById('slider')); var self = this; // (2) инициализировать слайдер, пробросить параметры this.$slider.slider(< min: this.getAttribute('min') || 0, max: this.getAttribute('max') || 100, value: this.getAttribute('value') || 0, slide: function() < // (3) пробросить событие var event = new CustomEvent("slide", < detail: < value: self.$slider.slider("option", "value") >, bubbles: true >); self.dispatchEvent(event); > >); >; document.registerElement('ui-slider', < prototype: SliderProto >);

Функция createdCallback по шагам:

  1. Создаём Shadow DOM, элемент #slider получаем из него, он не в основном документе.
  2. Используя jQuery UI, слайдер создаётся вызовом jQuery UI методом slider, который имеет вид $elem.slider(); . Параметры получаем из атрибутов (он же this ) и отдаём библиотеке. Она делает всю работу.
  3. Параметр slide задаёт функцию-колбэк, которая вызывается при передвижении слайдера и будет генерировать DOM-событие на элементе, на которое можно будет поставить обработчик при помощи addEventListener . В его деталях мы указываем новое значение слайдера.

Полный код с примером:

jquery.html
ui-slider.html

      ui-slider  elem.addEventListener("slide", function(e) < value.innerHTML = e.detail.value; // = this.value >);