1 of 51

Earth Engine User Interfaces and Apps

#GeoForGood19

2 of 51

How to build awesome UI in Earth Engine

Sufyan Abbasi

sufy@google.com

#GeoForGood19

3 of 51

How to think like a Google frontend engineer

Sufyan Abbasi

sufy@google.com

#GeoForGood19

4 of 51

UI is Challenging

It’s easy to go overboard!

#GeoForGood19

5 of 51

UI is Subjective

Two Internet Browsers, circa 1999

#GeoForGood19

6 of 51

Humans are asynchronous ⏰

“ I’ll let you know when I get to it! ”

#GeoForGood19

7 of 51

Goals for this session:

  1. Learn about the various Earth Engine widgets and how they operate.

  • Learn how to build beautiful Earth Engine apps.

  • Learn techniques to structure your code to make developing UIs easier.

#GeoForGood19

8 of 51

Logistics

Or:

✨ Go to this app: sufy.users.earthengine.app/view/g4g-ui-apps

#GeoForGood19

9 of 51

UI and Apps in Earth Engine

#GeoForGood19

10 of 51

#GeoForGood19

11 of 51

When Printing to the Console is Not Enough

  • Earth Engine Apps don’t have a console!

  • Earth Engine Apps let you communicate your analyses to a broader audience outside of the Earth Engine developer community.

  • We want to let users supply their own inputs into your analysis code in order to let them explore what they’re interested in.

#GeoForGood19

12 of 51

Earth Engine Apps are built from Widgets

  • Widgets are user interface components that let users of your app interact with your script.

  • Whenever a user interacts with one, a widget generates an event that your script listens for and executes a callback function that you supply.

#GeoForGood19

13 of 51

What kind of Widgets do we have in Earth Engine?

  1. Widgets that let you display information.

  • Widgets that let users input parameters or interact with your script.

  • Widgets that let you layout other widgets.

#GeoForGood19

14 of 51

What kind of Widgets do we have in Earth Engine?

  • Widgets that let you display information.

  • Widgets that let users input parameters or interact with your script.

  • Widgets that let you layout other widgets.

#GeoForGood19

15 of 51

Display Widget: ui.Label

ui.Label

ui.Chart

ui.Thumbnail

var label = ui.Label("Hello!");

label.setValue("Changed label.");

label.setUrl("https://earthengine.google.com");

Map.add(label);

#GeoForGood19

16 of 51

Display Widget: ui.Chart

ui.Label

ui.Chart

ui.Thumbnail

var chart = ui.Chart.image.series(

ndvi, point, ee.Reducer.mean(), 200);

chart.setOptions({

title: 'NDVI Over Time',

vAxis: {title: 'NDVI'},

hAxis: {

title: 'date',

format: 'MM-yy',

gridlines: {count: 7},

},

});

Map.add(chart);

#GeoForGood19

17 of 51

Display Widget: ui.Thumbnail

ui.Label

ui.Chart

ui.Thumbnail

ui.Thumbnail({

image: collection,

params: {

crs: 'EPSG:3857',

dimensions: '300',

region: rect,

min: -2000,

max: 10000,

palette: 'black, blanchedalmond, green, green',

framesPerSecond: 12,

}

});

See: Animated Thumbnail Example

#GeoForGood19

18 of 51

What kind of Widgets do we have in Earth Engine?

  • Widgets that let you display information.

  • Widgets that let users input parameters or interact with your script.

  • Widgets that let you layout other widgets.

#GeoForGood19

19 of 51

Input Widget: ui.Buttons

ui.Button

ui.CheckBox

ui.DateSlider

ui.Select

ui.Textbox

var button = ui.Button("Click me!");

button.onClick(function() {

print("I was clicked");

});

Map.add(button);

#GeoForGood19

20 of 51

Input Widget: ui.Checkbox

ui.Button

ui.CheckBox

ui.DateSlider

ui.Select

ui.Textbox

var checkbox = ui.Checkbox("Check me!");

checkbox.onChange(function(isChecked) {

if (isChecked) {

print("I'm checked");

} else {

print("I'm unchecked");

}

});

Map.add(checkbox);

#GeoForGood19

21 of 51

Input Widget: ui.DateSlider

ui.Button

ui.CheckBox

ui.DateSlider

ui.Select

ui.Textbox

var dateSlider = ui.DateSlider({

start: "2019-09-10",

end: "2019-09-20",

value: "2019-09-16",

});

dateSlider.onChange(function(dateRange) {

print(dateRange);

});

Map.add(dateSlider);

#GeoForGood19

22 of 51

Input Widget: ui.Select

ui.Button

ui.CheckBox

ui.DateSlider

ui.Select

ui.Textbox

var select = ui.Select(

['Option1', 'Option2', 'Option3'],

"Select an Option");

select.onChange(function(selected) {

print("Selected Option: " + selected);

});

Map.add(select);

#GeoForGood19

23 of 51

Input Widget: ui.Textbox

ui.Button

ui.CheckBox

ui.DateSlider

ui.Select

ui.Textbox

var textbox = ui.Textbox("Type Something");

textbox.onChange(function(text) {

print("Typed: " + text);

});

print(textbox.getValue());

Map.add(textbox);

#GeoForGood19

24 of 51

What kind of Widgets do we have in Earth Engine?

  • Widgets that let you display information.

  • Widgets that let users input parameters or interact with your script.

  • Widgets that let you layout other widgets.

#GeoForGood19

25 of 51

Layout Widget: ui.Map

ui.Map

ui.Panel

ui.SplitPanel

var map = ui.Map();

ui.root.clear();

ui.root.add(map);

map.addLayer(...);

map.onClick(...);

#GeoForGood19

26 of 51

Layout Widget: ui.Panel

ui.Map

ui.Panel

ui.SplitPanel

var panel = ui.Panel();

var title = ui.Label("Mini Map:");

panel.add(title);

panel.add(ui.Map());

panel.setLayout(

ui.Panel.Layout.flow("vertical"))

Map.add(panel);

#GeoForGood19

27 of 51

Layout Widget: ui.SplitPanel

ui.Map

ui.Panel

ui.SplitPanel

var leftMap = ui.Map();

var rightMap = ui.Map();

var splitPanel = ui.SplitPanel({

firstPanel: leftMap,

secondPanel: rightMap,

wipe: true, // false for resizable panels

orientation: "horizontal",

});

ui.root.clear();

ui.root.add(splitPanel);

#GeoForGood19

28 of 51

How do I work with widgets?

#GeoForGood19

29 of 51

But first, some JavaScript!

#GeoForGood19

30 of 51

Functions

A function is a block of code that executes when you call it by its name. They may also accept some inputs:

function sayHello(name) {

return "Hello, my name is " + name;

}

print(sayHello("Sufyan"));

Console Output:

> Hello, my name is Sufyan

#GeoForGood19

31 of 51

Dictionaries

An object is a data structure that allows you store key-value pairs. Input a key and it returns the value that you passed in:

var imageCollections = {

landsat: 'LANDSAT/LC08/C01/T1_RT',

sentinel: 'COPERNICUS/S5P/NRTI/L3_NO2',

}

print(imageCollections.landsat)

print(imageCollections['sentinel'])

imageCollections.srtm = 'CGIAR/SRTM90_V4’

Console Output:

> LANDSAT/LC08/C01/T1_RT

> COPERNICUS/S5P/NRTI/L3_NO2

#GeoForGood19

32 of 51

How do I work with widgets?

#GeoForGood19

33 of 51

Widget Workflow

  1. Make a widget: var button = ui.Button("Click Me");
  2. Make it listen to events: button.onClick(function() {

print("I was clicked.");

});

  • Add it to another widget: Map.add(button);
  • Style it: button.style().set('color', 'red');

button.style().set('position', 'top-right');

#GeoForGood19

34 of 51

A more compact form:

var button = ui.Button({

label: "Click Me",

onClick: function() {

print("I was clicked.");

},

style: {

color: 'red',

position: 'top-right',

},

});

Map.add(button);

#GeoForGood19

35 of 51

Result:

#GeoForGood19

36 of 51

How do I make my widgets useful?

#GeoForGood19

37 of 51

Event Handling: making your widgets interactive

By binding an event handler, or callback, to a user event, you can execute a function when the user does something.

#GeoForGood19

38 of 51

Event Handling: making your widgets interactive

By binding an event handler, or callback, to a user event, you can execute a function when the user does something.

Click Me!

ui.Button("Click Me!")

OnClick Handler

I was clicked!

Clicked.

button.onClick(function() {

button.setLabel("Clicked.");

})

Update the UI

#GeoForGood19

39 of 51

Event Handling Patterns

  • All of our widgets (except for ui.Label) have one of two event handlers: onClick or onChange, depending on the widget.

  • All of the onChange callback functions share the same pattern for inputs: the first parameter is the new input value and the second is the widget itself:

textbox.onChange(function(value, widget) {

print("Widget: " + widget + " has value: " + value);

});

#GeoForGood19

40 of 51

How do I make my app pretty?

#GeoForGood19

41 of 51

Making Layouts with ui.Panel and ui.Map

EE Apps “Bread and Butter” Template:

#GeoForGood19

42 of 51

Making Layouts with ui.Panel and ui.Map

Step 1: Make the side panel.

var sidePanel = ui.Panel({

layout: ui.Panel.Layout.flow('vertical'),

style: {

height: '100%',

width: '30%',

},

})

#GeoForGood19

43 of 51

Making Layouts with ui.Panel and ui.Map

Step 2: Make the map and legend.

var map = ui.Map();

var legendPanel = ui.Panel({

widgets: [ui.Label("Legend")],

layout: ui.Panel.Layout.flow('vertical'),

style: {

position: 'bottom-right',

},

});

map.add(legendPanel);

#GeoForGood19

44 of 51

Making Layouts with ui.Panel and ui.Map

Step 3: Combine the side panel and map into a ui.SplitPanel:

var splitPanel = ui.SplitPanel({

firstPanel: sidePanel,

secondPanel: map,

});

#GeoForGood19

45 of 51

Making Layouts with ui.Panel and ui.Map

Step 4: Clear the ui.root and add the split panel:

ui.root.clear();

ui.root.add(splitPanel);

#GeoForGood19

46 of 51

All that’s left...

#GeoForGood19

47 of 51

All that’s left… is the hard part.

#GeoForGood19

48 of 51

Example: NDVI Explorer (see Logistics)

#GeoForGood19

49 of 51

Styling Widgets

You can style widgets two ways:

  1. Supply a style property in the widget constructor (emulates CSS):

style: {

height: '100%',

width: '30%',

position: 'bottom-right'

}

  • Explicitly set a style property using widget.style().set(...):

widget.style().set('position': 'bottom-right');

#GeoForGood19

50 of 51

Styling Widgets

Easy styling properties (they use CSS syntax)

Property

Function

Example Values

padding

Puts padding around the widget

'10px' '10px 0px' '10px 5px 0px 5px'

margin

Adds space between widgets

'10px' '10px 0px' '10px 5px 0px 5px'

color

Changes the font color

'white' 'rgb(255,255,255)' '#ffffff'

backgroundColor

Changes the background color

'white' 'rgb(255,255,255)' '#ffffff'

fontWeight

Changes font weight

'bold' 'lighter' '100'

#GeoForGood19

51 of 51

Earth Engine User Interfaces and Apps

Intro to EE UI

Sufyan Abbasi

sufy@google.com

#GeoForGood19