Painéis e layouts

Painéis

Um ui.Panel é um contêiner de IU de nível superior em que os widgets são organizados. Cada ui.Panel tem um objeto ui.Panel.Layout que controla como os widgets são organizados na tela. Saiba mais na seção Layouts. Os painéis também mantêm uma lista de widgets (que podem incluir outros painéis) que foram adicionados a eles. Para gerenciar widgets no painel, add() ou remove() no painel ou extraia a lista de widgets chamando widgets() no painel. A lista de widgets é uma instância de ui.data.ActiveList, o que significa que você pode configurar o painel manipulando a lista e os widgets nela.

ui.root

O ui.root é uma instância fixa de um ui.Panel para tudo no editor de código abaixo da barra horizontal. Por padrão, ele contém apenas um widget: o mapa padrão. Especificamente, o item em ui.root.widgets().get(0) é o objeto Map (uma instância de ui.Map) que é exibido por padrão no editor de código. Além do alias Map, a única outra coisa especial sobre o mapa padrão é que ele tem ferramentas de edição de geometria. Para criar uma tela em branco para desenvolver a interface, clear() o mapa padrão de ui.root:

Editor de código (JavaScript)

ui.root.clear();

Também é possível modificar o mapa padrão no painel raiz adicionando widgets a ele. Especificamente, pense em um mapa como um painel com um layout absoluto (consulte a seção Layouts para mais detalhes). O exemplo a seguir ilustra uma modificação do mapa padrão:

Editor de código (JavaScript)

// Load a VIIRS surface reflectance image and display on the map.
var image = ee.Image('NOAA/VIIRS/001/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);
});

O exemplo modifica o mapa padrão (que é Map) tratando-o como um painel e adicionando widgets a ele. Como os mapas têm layout absoluto, a posição de um widget em um mapa é determinada por uma propriedade position da propriedade style do widget. Consulte a seção layout absoluto para mais detalhes.

Quando você compartilha um link do Code Editor com outro usuário, por padrão, o ui.root ocupa a maior parte da janela, e o editor de texto, o painel de documentos e o console ficam ocultos. Ao controlar o layout ui.root, você pode controlar a experiência de outros usuários com seu script.

Layouts

Os layouts controlam como os widgets em um painel são organizados para exibição. Há duas opções de layout, descritas abaixo: layout de fluxo e layout absoluto. Os layouts são especificados com a classe ui.Panel.Layout. Defina o layout de um painel no construtor ou com setLayout(). A ordem em que os widgets são adicionados determina como eles são organizados em um painel com layout de fluxo. A propriedade position do style de cada widget determina como um widget será organizado em um painel com layout absoluto. Se o estilo em um widget for irrelevante para o layout em que ele está colocado, ele será ignorado.

Fluxo

Um layout de fluxo mostra widgets em uma linha ('horizontal') ou uma coluna ('vertical'). Os widgets são organizados de acordo com a ordem em que são adicionados ao painel. Por exemplo, considere os seguintes botões adicionados a um painel:

Editor de código (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);

O layout vertical vai ficar assim:

ui_flow_layout.png

O width do painel está definido como 300 pixels, e o stretch está definido como 'horizontal' com a propriedade style. A propriedade de estilo stretch é aplicada a widgets em um painel com layout de fluxo. Por exemplo, {stretch: 'horizontal'} significa que o widget vai se expandir para preencher o espaço horizontal disponível no painel. No exemplo anterior, mude o tipo de layout de fluxo para 'horizontal' para ver os botões organizados em uma linha em vez de uma coluna.

Em um painel de fluxo horizontal, um widget esticado horizontalmente se expande para preencher o espaço disponível depois que todos os outros widgets ocuparem as larguras naturais. Se mais de um widget for esticado horizontalmente, o espaço horizontal disponível será dividido entre eles. Um widget esticado verticalmente se expande para preencher a altura do painel.

Em um painel de fluxo vertical, um widget esticado verticalmente se expande para preencher o espaço disponível depois que todos os outros widgets ocuparem as alturas naturais. Se mais de um widget for esticado verticalmente, o espaço vertical disponível será dividido entre eles. Um widget esticado horizontalmente se expande para preencher a largura do painel.

Absoluto

Um layout absoluto posiciona os widgets de acordo com as posições no painel. Ao contrário do layout de fluxo, a posição de um widget é determinada pela propriedade position da propriedade style do widget, e não pela ordem em que ele é adicionado ao painel. O exemplo a seguir demonstra o uso do painel root.ui com um layout absoluto (o layout do painel raiz é um fluxo horizontal por padrão, mas pode ser definido com ui.root.setLayout()):

Editor de código (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'));

O painel de layout absoluto vai ficar assim:

ui_absolute_layout.png

widgets()

Quando você adiciona um widget a um painel, ele é adicionado à lista de widgets do painel. Chamar widgets() no painel retorna o ui.data.ActiveList, que pode ser usado para manipular os widgets no painel. Considere o exemplo a seguir, que adiciona widgets a um painel, adiciona o painel ao painel raiz e atualiza um gráfico quando o usuário clica no mapa:

Editor de código (JavaScript)

// Load and display NDVI data.
var ndvi = ee.ImageCollection('NOAA/VIIRS/001/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);

Neste exemplo, observe que, primeiro, os widgets são adicionados ao painel usando add(). Na função de callback registrada para mapear cliques, a lista de widgets panel é modificada. Especificamente, o terceiro widget (que pode ou não existir) é definido de modo que um novo gráfico de NDVI seja exibido ao longo do tempo. Saiba mais sobre as funções de tratamento de eventos na página de eventos.