パネルとレイアウト

Panel

ui.Panel は、ウィジェットを配置する上位レベルの UI コンテナです。各 ui.Panel には、ウィジェットを画面にどのように配置するかを制御する ui.Panel.Layout オブジェクトがあります。詳しくは、レイアウトのセクションをご覧ください。パネルには、追加されたウィジェットのリスト(他のパネルを含む場合があります)も保持されます。パネル内のウィジェットを管理するには、パネルからウィジェットを add() または remove() するか、パネルで widgets() を呼び出してウィジェットのリストを取得します。ウィジェット リストは ui.data.ActiveList のインスタンスです。つまり、リストとその中のウィジェットを操作することでパネルを構成できます。

ui.root

ui.root は、コードエディタの横線の下にあるすべての要素の ui.Panel の固定インスタンスです。デフォルトでは、デフォルトの地図という 1 つのウィジェットのみが含まれています。具体的には、ui.root.widgets().get(0) の項目は、デフォルトで Code Editor に表示される Map オブジェクト(ui.Map のインスタンス)です。デフォルトの地図の特別な点は、Map エイリアス以外に、ジオメトリ編集ツールが含まれていることだけです。UI を構築する空のキャンバスを取得するには、ui.root からデフォルト マップを clear() します。

コードエディタ(JavaScript)

ui.root.clear();

または、ウィジェットを追加してルートパネルのデフォルト地図を変更することもできます。具体的には、地図を絶対レイアウトのパネルと考えてください(詳しくは、レイアウトのセクションをご覧ください)。次の例は、デフォルトの地図の変更を示しています。

コードエディタ(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);
});

この例では、デフォルトの地図(Map)をパネルとして扱い、ウィジェットを追加することで、デフォルトの地図を変更しています。地図には絶対レイアウトがあるため、地図上のウィジェットの位置は、ウィジェットの style プロパティの position プロパティによって決まります。詳しくは、絶対レイアウトのセクションをご覧ください。

Code Editor のリンクを他のユーザーと共有すると、デフォルトでは ui.root がウィンドウの大部分を占め、テキスト エディタ、ドキュメント パネル、コンソールが非表示になります。ui.root レイアウトを制御することで、他のユーザーがスクリプトをどのように使用するかを制御できます。

レイアウト

レイアウトは、パネル内のウィジェットをどのように表示するかを制御します。レイアウト オプションは、フロー レイアウトと絶対レイアウトの 2 つがあります。レイアウトは ui.Panel.Layout クラスで指定します。コンストラクタまたは setLayout() でパネルのレイアウトを設定します。ウィジェットを追加する順序によって、フロー レイアウトのパネル内でウィジェットがどのように配置されるかが決まります。各ウィジェットの position プロパティと style は、絶対レイアウトのパネル内でウィジェットをどのように配置するかを決定します。ウィジェットのスタイルが、ウィジェットが配置されているレイアウトと無関係な場合、そのスタイルは無視されます。

フロー

フローレイアウトでは、ウィジェットが行('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 ピクセルに設定され、stretchstyle プロパティで 'horizontal' に設定されています。stretch スタイル プロパティは、フロー レイアウトのパネル内のウィジェットに適用されます。たとえば、{stretch: 'horizontal'} は、ウィジェットがパネル内の使用可能な横方向のスペース全体に拡大されることを意味します。上の例では、フロー レイアウト タイプを 'horizontal' に変更して、ボタンが列ではなく行に並べられるようにします。

水平フロー パネルでは、水平方向に伸ばされたウィジェットは、他のすべてのウィジェットが自然なを占有した後に、利用可能なスペースを埋めるように拡大されます。複数のウィジェットが水平方向に伸ばされている場合、利用可能な水平方向のスペースはウィジェット間で分割されます。縦方向に伸ばされたウィジェットは、パネルの高さ全体に拡大されます。

垂直フロー パネルでは、垂直方向に伸ばされたウィジェットは、他のすべてのウィジェットが自然な高さを占有した後に、利用可能なスペースを埋めるように拡大されます。複数のウィジェットが縦方向に伸ばされている場合、利用可能な縦方向のスペースはウィジェット間で分割されます。横方向に伸ばされたウィジェットは、パネルのいっぱいに拡大されます。

絶対

絶対レイアウトでは、パネル内の位置に応じてウィジェットを配置します。フロー レイアウトとは異なり、ウィジェットの位置は、パネルに追加される順序ではなく、ウィジェットの style プロパティの position プロパティによって決まります。次の例は、絶対レイアウトで 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('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);

この例では、まず add() を使用してウィジェットがパネルに追加されます。マップのクリックに登録されたコールバック関数では、代わりに panel のウィジェットのリストが変更されます。具体的には、3 つ目のウィジェット(存在する場合もない場合もあります)は、時間の経過に伴う NDVI の新しいグラフが表示されるように設定されています。イベント処理関数について詳しくは、[イベント] ページをご覧ください。