Панели и макеты

Панели

ui.Panel – это контейнер верхнего уровня, в котором размещаются виджеты. У каждого объекта ui.Panel есть объект ui.Panel.Layout, который управляет расположением виджетов на экране. Подробнее о макетах… Панели также содержат список добавленных в них виджетов (в том числе других панелей). Чтобы управлять виджетами на панели, вы можете add() или remove() их, а также получить список виджетов, вызвав метод widgets(). Список виджетов – это экземпляр ui.data.ActiveList, а значит, вы можете настраивать панель, изменяя список и виджеты в нем.

ui.root

ui.root – это фиксированный экземпляр ui.Panel для всего, что находится в редакторе кода под горизонтальной полосой. По умолчанию он содержит только один виджет – карту. В частности, элемент ui.root.widgets().get(0) – это объект Map (экземпляр ui.Map), который по умолчанию отображается в редакторе кода. Помимо псевдонима Map, единственная особенность карты по умолчанию – наличие инструментов редактирования геометрии. Чтобы получить пустой холст для создания интерфейса, clear() карту по умолчанию из ui.root:

Редактор кода (JavaScript)

ui.root.clear();

Вы также можете изменить карту по умолчанию на корневой панели, добавив на нее виджеты. В частности, карту можно рассматривать как панель с абсолютным макетом (подробнее см. в разделе Макеты). В следующем примере показано, как изменить карту по умолчанию.

Редактор кода (JavaScript)

// Load a VIIRS surface reflectance image and display on the map.
var image = ee.Image('NASA/VIIRS/002/VNP09GA/2022_06_05').select('M.*');
Map.addLayer(image, {bands: ['M5', 'M4', 'M3'], min: 0, max: 4e3, gamma: 1.5});

// Create the title label.
var title = ui.Label('Click to inspect');
title.style().set('position', 'top-center');
Map.add(title);

// Create a panel to hold the chart.
var panel = ui.Panel();
panel.style().set({
  width: '400px',
  position: 'bottom-right'
});
Map.add(panel);

// Register a function to draw a chart when a user clicks on the map.
Map.style().set('cursor', 'crosshair');
Map.onClick(function(coords) {
  panel.clear();
  var point = ee.Geometry.Point(coords.lon, coords.lat);
  var chart = ui.Chart.image.regions(image, point, null, 30);
  chart.setOptions({title: 'Band values'});
  panel.add(chart);
});

Обратите внимание, что в примере изменяется карта по умолчанию (Map), которая рассматривается как панель, и на нее добавляются виджеты. Поскольку карты имеют абсолютный макет, положение виджета на карте определяется свойством position свойства style виджета. Подробные сведения приведены в разделе Абсолютный макет.

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

Макеты

Макеты определяют, как виджеты на панели будут расположены на экране. Существует два варианта макета: макет с плавающим размещением и макет с абсолютным размещением. Макеты задаются с помощью класса ui.Panel.Layout. Макет панели можно задать в конструкторе или с помощью метода setLayout(). Порядок добавления виджетов определяет их расположение на панели с макетом потока. Свойство position каждого виджета style определяет, как виджет будет расположен на панели с абсолютным макетом. Если стиль виджета не соответствует макету, в котором он размещен, он игнорируется.

Flow

Макет FlowLayout отображает виджеты в строке ('horizontal') или столбце ('vertical'). Виджеты упорядочиваются в соответствии с порядком, в котором они добавляются на панель. Например, на панель добавлены следующие кнопки:

Редактор кода (JavaScript)

// Create a panel with vertical flow layout.
var panel = ui.Panel({
  layout: ui.Panel.Layout.flow('vertical'),
  style: {width: '300px'}
});

// Add a bunch of buttons.
for (var i = 0; i < 30; i++) {
  panel.add(ui.Button({label: 'Button ' + i, style: {stretch: 'horizontal'}}));
}

ui.root.clear();
ui.root.add(panel);

Вертикальный макет должен выглядеть примерно так:

ui_flow_layout.png

Обратите внимание, что для свойства width панели задано значение 300 пикселей, а для свойства stretch – значение 'horizontal' (с помощью свойства style). Свойство стиля stretch применяется к виджетам на панели с макетом потока. Например, {stretch: 'horizontal'} означает, что виджет будет расширяться, чтобы заполнить доступное горизонтальное пространство на панели. В предыдущем примере измените тип макета на 'horizontal', чтобы кнопки располагались в ряд, а не в столбец.

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

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

Абсолютное значение

Абсолютный макет размещает виджеты в соответствии с их позициями на панели. В отличие от макета Flow, положение виджета определяется свойством position свойства style виджета, а не порядком, в котором он добавляется на панель. В следующем примере показано, как использовать панель root.ui с абсолютным макетом (по умолчанию макет корневой панели является горизонтальным, но его можно задать с помощью ui.root.setLayout()):

Редактор кода (JavaScript)

ui.root.clear();
ui.root.setLayout(ui.Panel.Layout.absolute());

// A function to make buttons labeled by position.
function makeButton(position) {
  return ui.Button({
    label: position,
    style: {position: position}
  });
}

// Add labeled buttons to the panel.
ui.root.add(makeButton('top-left'));
ui.root.add(makeButton('top-center'));
ui.root.add(makeButton('top-right'));
ui.root.add(makeButton('middle-left'));
ui.root.add(makeButton('middle-right'));
ui.root.add(makeButton('bottom-left'));
ui.root.add(makeButton('bottom-center'));
ui.root.add(makeButton('bottom-right'));

Панель абсолютного макета должна выглядеть примерно так:

ui_absolute_layout.png

widgets()

Когда вы добавляете виджет на панель, он появляется в списке виджетов этой панели. Вызов widgets() на панели возвращает ui.data.ActiveList, который можно использовать для управления виджетами на панели. Рассмотрим следующий пример, в котором виджеты добавляются на панель, панель добавляется на корневую панель, а затем диаграмма обновляется, когда пользователь нажимает на карту:

Редактор кода (JavaScript)

// Load and display NDVI data.
var ndvi = ee.ImageCollection('NASA/VIIRS/002/VNP13A1')
    .filterDate('2021-01-01', '2022-01-01').select('NDVI');
Map.addLayer(
  ndvi.median(), {min: 0, max: 10000, palette: ['99c199', '006400']}, 'NDVI');

// Configure the map.
Map.setCenter(-94.84497, 39.01918, 8);
Map.style().set('cursor', 'crosshair');

// Create an empty panel in which to arrange widgets.
// The layout is vertical flow by default.
var panel = ui.Panel({style: {width: '400px'}})
    .add(ui.Label('Click on the map'));

// Set a callback function for when the user clicks the map.
Map.onClick(function(coords) {
  // Create or update the location label (the second widget in the panel)
  var location = 'lon: ' + coords.lon.toFixed(2) + ' ' +
                 'lat: ' + coords.lat.toFixed(2);
  panel.widgets().set(1, ui.Label(location));

  // Add a red dot to the map where the user clicked.
  var point = ee.Geometry.Point(coords.lon, coords.lat);
  Map.layers().set(1, ui.Map.Layer(point, {color: 'FF0000'}));

  // Create a chart of NDVI over time.
  var chart = ui.Chart.image.series(ndvi, point, ee.Reducer.mean(), 200)
      .setOptions({
        title: 'NDVI Over Time',
        vAxis: {title: 'NDVI'},
        lineWidth: 1,
        pointSize: 3,
      });

  // Add (or replace) the third widget in the panel by
  // manipulating the widgets list.
  panel.widgets().set(2, chart);
});

// Add the panel to the ui.root.
ui.root.add(panel);

В этом примере виджеты сначала добавляются на панель с помощью add(). В функции обратного вызова, зарегистрированной для кликов по карте, вместо этого изменяется список виджетов panel. В частности, третий виджет (который может существовать или не существовать) настроен таким образом, что отображается новая диаграмма NDVI за определенный период времени. Подробнее о функциях обработки событий…