Списки атрибутов должны быть знакомы всем. Обычно список атрибутов, созданный с использованием HTML5, представляет собой раскрывающееся меню. И во многих случаях раскрывающийся список недостаточно хорош. Что мне делать? Я попытался использовать HT для Интернета, чтобы реализовать функцию нажатия кнопки на панели свойств, чтобы открыть многофункциональное поле выбора и выбрать входящие данные. Я считаю, что общая практика относительно проста и удобна, поэтому я поделюсь. это с тобой здесь.
визуализацииhttp://www.hightopo.com/demo/propertyEditor/index.html
Реализация кода Карта топологииИз приведенного выше рендеринга мы видим, что вся страница разделена на 3 части: часть топологии GraphView слева, часть таблицы TableView в правом нижнем углу и часть атрибута PropertyView в правом верхнем углу. Сначала мы разделяем всю сцену, а затем добавляем в каждую часть конкретный контент:
gv = new ht.graph.GraphView();var tablePane = new ht.widget.TablePane(gv.dm());//Компонент панели таблицы propertyView = new ht.widget.PropertyView(gv.dm());/ /formPane находится в свойствеView, поэтому сначала необходимо определить var rightView = new ht.widget.SplitView(propertyView, tablePane, 'v', 0.4); // Разделяем компонент, v делится на верхний и нижний слои, соотношение 0,4:0,6rightView.getView().style.borderLeft = '1px Solid #000';var borderPane = new ht .widget.BorderPane( );//Компонент панели границ borderPane.setRightView(rightView, 400);//Установить borderPane Правый компонент — rightView с шириной 400borderPane.setCenterView(gv);//Установим средний компонент borderPane на gv borderPane.addToDOM();//Добавим компонент borderPane в тело
Все новые части в приведенном выше коде являются инкапсулированными компонентами HT, которые эквивалентны классам. Ниже приводится объяснение компонента разделения SplitView. Компонент разделения используется для разделения двух подкомпонентов влево и вправо или вверх и вниз. -компоненты могут быть компонентами, предоставленными платформой HT, или это может быть собственный компонент HTML. Субкомпонент позиционируется абсолютно с абсолютным положением. Параметры в этом компоненте: (левый компонент или верхний компонент, правый компонент или. нижний компонент, h означает левое и правое деление v Указывает верхнее и нижнее деление. Значение позиции деления по умолчанию составляет 0,5. Если значение настройки составляет 0–1, оно будет разделено в процентах. Значение больше 1 представляет собой абсолютную ширину или высоту левого или верхнего компонента. Меньше 1 представляет абсолютную ширину или высоту правого или нижнего компонента ); а компонент панели BorderPane представляет собой контейнер макета, который может размещать подкомпоненты в пяти областях: сверху, снизу, слева, справа и по центру. Субкомпоненты могут быть компонентами, предоставляемыми платформой HT, или собственными компонентами HTML. Компонент позиционируется. Выполните абсолютное позиционирование для абсолютного режима. Здесь я объединяю SplitView и BorderPane, чтобы разделить сцену на три части. Наконец, не забудьте добавить окончательный контейнер макета в тело или любой HTML-тег, чтобы его можно было отобразить в интерфейсе. Определение addToDOM следующее:
addToDOM = function(){ var self = this, view = self.getView(), //Получаем базовый элемент div этого компонента style = view.style; //Получаем атрибут стиля базового элемента div document.body.appendChild( view) ; //Добавляем базовый элемент div в тело style.left = '0'; //HT по умолчанию определяет компоненты для определения абсолютного позиционирования, поэтому необходимо установить позицию style.right = '0'; верх = '0'; style.bottom = '0'; window.addEventListener('resize', function () { self.iv(); }, false };
Компоненты HT обычно встраиваются в контейнеры, такие как BorderPane, SplitView и TabView. Самый внешний компонент HT требует, чтобы пользователь вручную добавил базовый элемент div, возвращаемый getView(), в элемент DOM страницы. Здесь необходимо отметить, что. , При изменении размера родительского контейнера, если родительским контейнером являются предопределенные компоненты контейнера HT, такие как BorderPane и SplitView, контейнер HT автоматически рекурсивно вызывает функцию недействительности дочернего компонента, чтобы уведомить об обновлении. Но если родительский контейнер является собственным элементом HTML, компонент HT не может знать, что его необходимо обновить. Поэтому самый внешний компонент HT обычно должен прослушивать событие изменения размера окна и вызывать функцию недействительности самого внешнего. компонент для обновления.
Сцена создана. Чтобы показать различия атрибутов, соответствующих разным узлам, мы добавили на карту топологии семь узлов:
function initModel(){ var name = device; var count = 0; var root = createNode(name + count++, name + (++count));//Параметр 1 — имя, параметр 2 — тег root.setImage('. /symbols/computer room/server.json'); root.setName('server'); root.s('label.position', 3); gv.sm().ss(root);//Корневой узел выбирается по умолчанию for (var i = 0; i < 2; i++) { var iNode = createNode(name + count++, name + (++count) );/ /Параметр 1 — имя, параметр 2 — тег createEdge(root, iNode); for (var j = 0; j < 2; j++) { var jNode = createNode(name + count++, name + (++count)); createEdge(iNode, jNode } }});
Объявление функции createNode выглядит следующим образом:
функция createNode(имя, тег){//Create Node node flag++; var node = new node.setName(name); node.setImage('./symbols/computer room); / XX subsystem.json'); node.a('скрытый', false);//Пользовательские атрибуты, вы можете управлять node.a('hidden') для управления видимостью узлов node.a('Тип интерфейса', 'SATA'); node.a('Видеокарта', 'Nvidia'); ') ; if(flag % 2 === 0){ node.a('тип интерфейса', 'IDE'); node.a('видеокарта', 'ATI'); node.s('label. позиция', 11); gv.dm().add(node);//Добавляем узлы в контейнер данных DataModel node.tablePane1 = createTableView(serviceType, dataModel1);//Создаем панель таблицы node.tablePane2 = createTableView(serviceSize, dataModel2 node). tablePane3 = createTableView (версия, dataModel3); node.formPane1 =; createFormPane(node.tablePane1);//Создаем панель формы node.formPane1.title = 'Type';//Чтобы подготовить заголовок последующего диалогового окна node.formPane2 = createFormPane(node.tablePane2); title = 'Память'; node.formPane3 = createFormPane(node.tablePane3.title = 'Модель'); if(flag % 3 === 0){ node.formPane3.v('tag', 'Lenovo Server X3650M5 8871' }else{ node.formPane3.v('tag', 'Lenovo IBM X3250 5458I21 '); } node.a('model', node.formPane3.v('tag')); return node;}
Мы контролируем видимость узла, управляя скрытым атрибутом этого узла и используя функцию визуального фильтра setVisibleFunc в GraphView:
gv.setVisibleFunc(function(data){ if(data.a('hidden')){ return false; } return true;});Панель свойств
При использовании узлов естественно отображать атрибуты. Вместе со значениями на панели таблицы tablePane ниже добавляется всего семь атрибутов:
function createProperty(){//Создайте свойства propertyView.addProperties([ { name: 'name',//Получите атрибут name в сочетании с атрибутом accessType, чтобы окончательно получить доступ к атрибутам узла. Значение accessType по умолчанию равно нулю, например поскольку имя — это возраст, для доступа используйте метод get/set или is/set методов getAge() и setAge(98) (имя здесь — это имя, поэтому получите его через getName()) displayName: 'Name'//Установить отображаемое текстовое значение имени атрибута}, { name: 'hidden',//Получить скрытый атрибут displayName: 'Hide this node', accessType: 'attr',//Если имя скрыто, используйте getAttr('hidden') и setAttr('hidden', false) для доступа к значку: 'images/alert.gif', //Установите тип значения значка, отображаемый слева от имени атрибута: 'boolean', //Используется, чтобы предложить компоненту предоставить подходящий рендеринг логического типа, отображается в виде флажка editable: true //Устанавливает, является ли свойство редактируемым}, { name: 'grade', displayName: 'Type' , accessType: 'attr', drawPropertyValue: function(g, property, value, rowIndex, x, y, w, h, data, view){//Функция рендеринга значения пользовательского атрибута var cb = function(v) { data.a('grade', v); } return fillFormPane(data.formPane1, w, h, data.tablePane1, serviceType, cb); { name: 'number', displayName: 'memory', accessType: 'attr', drawPropertyValue: функция (g, свойство, значение, rowIndex, x, y, w, h, данные, представление) { var cb = function (v) { data.a('number', v); } return fillFormPane(data.formPane2, w, h, data.tablePane2, serviceSize, cb); { name: 'Interface Type', accessType: 'attr', displayName); : 'Тип интерфейса' }, { name: 'Видеокарта', accessType: 'attr', displayName: 'Видеокарта' }, { name: 'Модель', accessType: 'attr', displayName: 'Модель', } ]);}
Возвращаемое значение атрибута drawPropertyValue в третьем и четвертом атрибутах — это функция fillFormPane. Параметры этой функции: (компонент формы formP, ширина компонента формы w, высота компонента формы h, нажмите кнопку в компоненте формы, чтобы создать таблицу. компонент tableP во всплывающем окне, содержимое массива arr в компоненте таблицы, функция cb присваивает значение, возвращаемое двойным щелчком мыши по строке в компоненте таблицы, текстовому полю ht.widget.TextField в форме).
Первый параметр formP — это создание компонента формы. Создание компонента формы заключается в создании компонента формы и добавлении текстового поля и кнопки в компонент формы. В HT этот шаг также довольно прост:
function createFormPane(tPane) {//Создаем панель формы var formPane = new ht.widget.FormPane(); formPane.setPadding(0); // Устанавливаем расстояние вокруг формы и содержимого компонента var tField = new ht.widget.TextField();//Создаем текстовое поле tField.setText('');//Содержимое текстового поля пусто tField.setDisabled(true);//Текстовое поле неработоспособно formPane.addRow( [//Добавляем строку в форму { id: 'tag', //Атрибут уникальной идентификации можно получить через formPane.getItemById(id) и добавить в соответствующий элемент объекта item: tField//Значением атрибута могут быть собственные элементы HTML, самостоятельно нарисованная текстовая информация внутри FormPane и встроенные компоненты HT, такие как Button, CheckBox, ComboBox и т. д.}, { button:{//После установки этого атрибута HT будет автоматически создаваться на основе значения атрибута объекта ht.widget.Button и сохраняться в метке атрибута элемента:'...',//Текстовое содержимое кнопки onClicked: function(){//Событие нажатия кнопки for(var я = 0; я < tPane.dm().size(); i++){//Set tablePane, чтобы выбрать значение, соответствующее formPane по умолчанию var data = tPane.dm().getDatas().get(i); 'value' ) === formPane.v('tag')){ tPane.sm().ss(data); } return createDialog(tPane, formPane);//Возвращается создание диалогового окна, содержимым которого является панель таблицы} } }], [0.5, 0.1]);//Устанавливаем соотношение отображения первого элемента и второго элемента в компонент таблицы. Этот компонент таблицы имеет всего два элемента: текстовое поле и кнопку, с пропорциями 0,5 и 0,1 соответственно, возвращающими formPane;}
Процесс создания функции createDialog также прост и понятен. Заголовок, размер, содержимое и т. д. диалогового окна настраиваются с помощью метода setConfig(config). Я передал компонент таблицы параметров tPane в createDialog, который используется как. содержимое, отображаемое в диалоговом окне:
function createDialog(tPane){//Создаем всплывающее окно диалога.setConfig({ title: gv.sm().ld().getName()++formPane.title,//Заголовок содержимого диалогового окна: tPane, // Непосредственно устанавливаем содержимое всплывающего окна на ширину панели таблицы: 400, //Указываем ширину диалогового окна, высоту: 200, перетаскивание: true, //Указывает, можно ли перетаскивать и корректировать диалоговое окно. closeable: true, //Указывает, следует ли отображать кнопку закрытия. maximizable: true, //Указывает, можно ли развернуть диалоговое окно: wh, // Переместите указатель мыши вправо от диалогового окна. Размер диалогового окна можно изменить в нижнем углу, что означает, что ширину и высоту можно регулировать кнопками: [//Добавить две кнопки { label: 'Cancel', действие: функция() { диалог.hide() } }, { метка: 'ОК ', } ] }); диалог.show();//Показать диалоговое окно}
Четвертый компонент таблицы tableP не представляет собой ничего особенного. Он просто создает компонент формы, а затем добавляет столбцы в компонент формы. Шаги просты, и код также довольно прост:
function createTableView(arr, dm){//Создать компонент таблицы var tableView = new ht.widget.TableView(dm); tableView.addColumns([//Добавить информацию о столбце в пакетном режиме, используя параметры массива json { displayName: 'ID', / /Получаем содержимое имени столбца заголовка таблицы drawCell: function(g, data, selected, columns, x, y, w, h, tableView){//Настраиваемый метод рендеринга ячеек var id = tableView.getRowIndex(data);//Вернем индекс строки, в которой расположен объект данных ht.Default.drawText(g, 'row' + (id + 1), null, null, x, y, w, h, 'center'); // Параметры рисования текста (объект кисти g, значение текстового содержимого, шрифт текста, цвет текста, координата x при начале рисования, координата y при начале рисования по y, ширина при рисовании w, высота при рисовании h , выравнивание текста по горизонтали, vAlign выравнивание текста по вертикали) } }, { displayName: 'Name', drawCell: function(g, data, selected, columns, x, y, w, h, tableView) { var id = tableView.getRowIndex(data); var info = arr[id]; ht.Default.drawText(g, info, null, null, x, y, w, h, 'center'); return tableView; }
После объяснения параметров fillFormPane давайте посмотрим, как определяется эта функция. По сути, последний шаг — щелкнуть элемент в компоненте таблицы tablePane и вернуть этот элемент в текстовое поле textField в компоненте формы formPane:
функция fillFormPane(formP, w, h, tableP, arr, cb){//formpane справа if(formP === undefined) { return; formP.setWidth(w); formP.setHeight(h); setHGap (0); if(formP.v('тег') === 'неопределено' || formP.v('тег') === '') { formP.v('tag', arr[0]); } tableP.onDataDoubleClicked = function(data){//Callback при двойном щелчке по строке данных в компоненте таблицы var v = arr[data.a('index) ') ]; formP.v('tag', v);//Установим соответствующее значение элемента элемента в соответствии с идентификатором, который является аббревиатурой setValue. Элемент с идентификатором тега представляет собой текстовое поле диалога.hide( ); если (cb){cb(v);} //Если передан параметр cb, установите значение data.a('number')/data.a('helloName') на значение строки, по которой дважды щелкнули мышью. в таблице, то есть присвоено третьему и четвертому атрибутам} tableP.onDataClicked = function(data){//Вызывается при нажатии на строку данных в компоненте таблицы, диалог.getConfig().buttons[1].action = function(){//Нажмите «ОК», чтобы продолжить следующие операции: var v = arr[data.a('index')]; formP.v('tag', v), if (cb); { cb(v);} } }; return formP.getView();}
функция fillFormPane(formP, w, h, tableP, arr, cb){//formpane справа if(formP === undefined) { return; formP.setHeight(h); setHGap (0); if(formP.v('тег') === 'неопределено' || formP.v('тег') === '') { formP.v('tag', arr[0]); } tableP.onDataDoubleClicked = function(data){//Callback при двойном щелчке по строке данных в компоненте таблицы var v = arr[data.a('index) ') ]; formP.v('tag', v);//Установим соответствующее значение элемента элемента в соответствии с идентификатором, который является аббревиатурой setValue. Элемент с идентификатором тега представляет собой текстовое поле диалога.hide( ); если (cb){cb(v);} //Если передан параметр cb, установите значение data.a('number')/data.a('helloName') на значение строки, по которой дважды щелкнули мышью. в таблице, то есть присвоено третьему и четвертому атрибутам} tableP.onDataClicked = function(data){//Вызывается при нажатии на строку данных в компоненте таблицы, диалог.getConfig().buttons[1].action = function(){//Нажмите «ОК», чтобы продолжить следующие операции: var v = arr[data.a('index')]; formP.v('tag', v), if (cb); { cb(v);} } }; return formP.getView();}
На этом отображение панели свойств в правом верхнем углу заканчивается. Аналогично создается панель таблицы в правом нижнем углу. Код можно прочитать, чтобы разобраться самостоятельно.
авторазметкаНаконец, давайте поговорим о расположении узлов во всем интерфейсе. Компонент автоматической компоновки autolayout в HT предоставляет несколько типов алгоритмов для автоматического расположения узлов на основе взаимосвязи между узлами и соединениями. Автоматическая компоновка часто используется в сценах, где имеется много графических элементов или сложные связи, что затрудняет их перетаскивание и размещение вручную. Я представляю каждый метод макета с помощью кнопок. Нажмите соответствующую кнопку, и метод макета будет автоматически размещен в соответствии с методом макета, установленным нажатой кнопкой:
Сначала создайте новый экземпляр, передайте ему объект, который требует автоматического макета (это может быть DataModel, GraphView и Graph3dView), а затем установите метод макета по умолчанию:
autoLayout = new ht.layout.AutoLayout(gv);setTimeout(function(){layout('towardsouth', true);//Поскольку перед загрузкой изображения автоматический макет размещается в соответствии с размером узла по умолчанию} , 200);
Затем создайте панель формы formPane, добавьте ее в тело и поместите в верхний левый угол тела. Я не буду вставлять весь код, просто отобразю кнопку первого макета:
function createDirectionForm(){ var form = new ht.widget.FormPane(); form.setWidth(200); //Установим ширину формы form.setHeight(80); document.body.appendChild(form.getView()); form.getView().style.background = '#fff'; form.getView().style.boxShadow = '4px 16px; 16px rgba(0, 0, 0, 0.1)';//Установим стиль тени form.addRow([//Эта строка вынесена отдельно как заголовок { element: 'Auto Layout:',//Отображаемый текст}] , [0.1]);//В массиве только один объект, просто задайте ширину одного объекта form.addRow([ { button: { icon: 'Layout/South Layout.json', onClicked: function() {layout('towardsouth', true }, background: null, labelColor: '#fff', groupId: 'btn', ToolTip: 'south Layout', borderColor: null } }, //.. . .Далее добавьте оставшиеся 6 кнопок], [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]);//В массиве семь объектов, поэтому необходимо задать ширину семи объектов return form;}
Это наиболее интересные части. Спасибо всем за чтение. Надеюсь, это будет полезно для вашего изучения. Я также надеюсь, что все поддержат сеть боевых искусств VeVb.