I'm trying to export Global Surface Water imagery using earth engine code editor. I want to include a scale bar over the region of interest in the exported image... how easy is this to accomplish? I've already extracted an image as a TIFF, would it be easier to open the TIFF in ArcGIS to add the scale bar or is there some javascript that could be added to address this? Not sure where to begin!

I note that GEE shows a little scale bar already on the lower right hand corner, but this doesn't get preserved in the image I download.

Existing image port is below:

var gsw = ee.Image('JRC/GSW1_0/MonthlyRecurrence/08');
var recurrence = gsw.select('monthly_recurrence');


// Calculations

// Create visualization layers. 
var recurrence2 = recurrence.updateMask(recurrence.divide(100))

var recurrence2RGB = recurrence2.visualize({
  palette: ['#FF7F27', '#99D9EA']

// Map Layers

print('Image to export: ', recurrence2RGB);
  eeObject: recurrence2RGB,
  shown: true

  image: recurrence2RGB,
  description: '08',
  scale: 30,
  region: geometry,
  crs: 'EPSG:3857'

2 Answers 2


The GEE Team is currently still working on Legend support. (source)

In the meantime you could use a scalebar script by Gennadii Donchyts.

 * Draws a scalebar
var Scalebar = {
  draw: function (pos, props) {
    var scale = Map.getScale()
    var units = 'km'
    var steps = 5
    var multiplier = 1000
    var palette = ['000000', 'ffffff']
    var format = '%.0f'
    var round = true

    if(props) {
      scale = props.scale || scale
      units = props.units || units
      steps = props.steps || steps
      multiplier = props.multiplier || multiplier
      palette = props.palette || palette
      format = props.format || format
      round = props.round !== 'undefined' ? props.round : round

    var p = ee.Number(Map.getScale()).divide(ee.Image().projection().nominalScale())
    var pt0 = ee.List(pos.coordinates().get(0))
    var pt1 = ee.List(pos.coordinates().get(1))

    // scalebar
    var bounds = pos.buffer(Map.getScale() * 2).bounds()
    var ll = ee.List(ee.List(bounds.coordinates().get(0)).get(0))
    var ur = ee.List(ee.List(bounds.coordinates().get(0)).get(2))
    var width = ee.Number(ur.get(0)).subtract(ll.get(0))
    var height = ee.Number(ur.get(1)).subtract(ll.get(1))

    var origin = ee.Image.constant(ll.get(0)).addBands(ee.Image.constant(ll.get(1)))

    var scalebar = ee.Image.pixelLonLat()
      .divide([width, height]).multiply([steps, 1])

    // units
    var point = translate(pt1, p.multiply(-8), p.multiply(-7))
    var imageUnits = Text.draw(units, ee.Geometry.Point(point), scale, {
      fontSize:18, textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.6})

    // define base images
    var images = ee.List([
      scalebar.visualize({min:0, max:1, forceRgbOutput: true, palette: palette}),
      ee.Image().paint(bounds, 1, 1).visualize({palette:['000000']}),

    // add labels
    var boundsMeters = bounds.transform(ee.Projection('EPSG:3857'), ee.ErrorMargin(1))
    var ll = ee.List(ee.List(boundsMeters.coordinates().get(0)).get(0))
    var ur = ee.List(ee.List(boundsMeters.coordinates().get(0)).get(2))
    var widthTargetUnits = ee.Number(ur.get(0)).subtract(ee.Number(ll.get(0))).divide(100).floor().multiply(100)

    for(var i=0; i<steps+1; i++) {
      var markerText = widthTargetUnits.divide(steps * multiplier).multiply(i).format(format)

      var point = translate(

      var imageLabel = Text.draw(markerText, ee.Geometry.Point(point), scale, {
        fontSize:18, textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.6})

      images = images.add(imageLabel)

    return ee.ImageCollection.fromImages(images).mosaic()

It seems that the distances of the scalebar produced by Donchyts script is unequal to the distances shown by Google Maps scalebar (left image). When I change the projection to EPSG:32610 it seems to fit better (right image).

Comparison of scalebars Comparison of scalebars

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.