Skip to content

p5.geo API reference ​

p5.geo targets p5.js 2.x. Coordinates are always latitude, longitude, in that order.

createGeoMap([options]) ⇒ GeoMap ​

Creates a map behind the canvas. Call it after createCanvas().

The canvas stays on top, transparent and click-through: the map handles dragging and scrolling, and mouseX, mouseY and p5's mouse events keep working. Call clear() (not background()) at the start of draw() so the map stays visible.

MapLibre GL JS is loaded automatically from jsDelivr, and attribution for the map data is shown automatically. The map can't be rotated or tilted, because shapes drawn on the canvas couldn't follow.

Kind: global function

ParamTypeDefaultDescription
[options]Object
[options.center]Array.<number> | LatLon[0, 0]Where the map is centered, as [lat, lon] or { lat, lon } ({ lat, lng } also works).
[options.zoom]number2Zoom level. See zoom.
[options.basemap]string | Object | false"'positron'"'positron', 'liberty' or 'bright' (keyless OpenFreeMap styles), a MapLibre style URL or style object, or false for no map: then nothing is added to the page and the GeoMap only converts coordinates.
[options.interactive]booleantrueWhether the map can be dragged and zoomed. With false, it stays where the sketch puts it. See interactive.
[options.mapOptions]ObjectExtra options for maplibregl.Map.
[options.maplibregl]ObjectA MapLibre GL JS namespace to use instead of loading one. A global maplibregl is also used if present.

Example

js
let myMap;

function setup() {
  createCanvas(800, 600);
  myMap = createGeoMap({ center: [35.68, 139.76], zoom: 12 });
}

function draw() {
  clear();
  const p = myMap.toScreen(35.6586, 139.7454); // Tokyo Tower
  circle(p.x, p.y, 20);
}

GeoMap ​

The geographic view of a sketch: where the map is centered, how far it is zoomed, and how latitude/longitude map onto the canvas. Create one with createGeoMap.

With a basemap (the default), MapLibre draws the map behind the p5 canvas and handles dragging and scrolling; the canvas stays transparent and click-through. With basemap: false, it only converts coordinates, with no map and no changes to the page.

Methods accept numeric strings as well as numbers (see Passing numbers and strings).

Kind: global class

myMap.ready : Promise.<GeoMap> ​

Resolves to the GeoMap once the basemap has been created, or right away with basemap: false. There's no need to wait for it to draw: toScreen() works from the start.

Kind: instance property of GeoMap

myMap.maplibre : Object ​

The underlying maplibregl.Map, for anything p5.geo doesn't cover. null until ready resolves, and always null with basemap: false.

Kind: instance property of GeoMap

myMap.toScreen(lat, [lon]) ⇒ p5.Vector | Array.<p5.Vector> ​

Converts a latitude and longitude to a position on the canvas.

Also accepts { lat, lon } or [lat, lon], or an array of them, which returns an array of vectors. Use the array form for lines and polygon outlines, such as the path, outer and holes from geoLines and geoPolygons.

The basemap repeats the world sideways, so a single point goes on the copy of the world nearest the center of the canvas. An array is moved as one piece, so shapes never tear apart across the antimeridian. Works before the basemap has loaded.

Positions are measured from the top-left corner, like mouseX and mouseY. On a WEBGL canvas, where (0, 0) is the center, call translate(-width / 2, -height / 2) before drawing.

Kind: instance method of GeoMap
Returns: p5.Vector | Array.<p5.Vector> - The position on the canvas, or one per point.

ParamTypeDescription
latnumber | LatLon | Array.<number> | Array.<LatLon>Latitude, or a point, or an array of points.
[lon]numberLongitude, when lat is a number.

Example

js
const p = myMap.toScreen(35.6586, 139.7454);
circle(p.x, p.y, 20);

Example

js
beginShape();
for (const p of myMap.toScreen(country.outer)) vertex(p.x, p.y);
endShape(CLOSE);

myMap.fromScreen(x, y) ⇒ LatLon ​

Converts a position on the canvas to a latitude and longitude.

Kind: instance method of GeoMap

ParamType
xnumber
ynumber

Example

js
const here = myMap.fromScreen(mouseX, mouseY);
text(`${here.lat.toFixed(4)}, ${here.lon.toFixed(4)}`, mouseX, mouseY);

myMap.contains(item, x, y, [distance]) ⇒ boolean ​

Whether a position on the canvas hits a shape, as drawn with toScreen(). What counts depends on what you pass:

  • a polygon from geoPolygons (or an outline as an array of { lat, lon }): inside its outline and outside every hole;
  • a line from geoLines: within distance pixels of it (default 5);
  • a point from geoPoints, or { lat, lon }: within distance pixels of it (default 10). Pass the radius of the circle you draw.

For the mouse, use isMouseOver.

Kind: instance method of GeoMap

ParamTypeDescription
itemObject | Array.<LatLon>A polygon, line or point.
xnumber
ynumber
[distance]numberFor lines and points, in pixels.

Example

js
const touched = countries.filter((c) => myMap.contains(c, touches[0].x, touches[0].y));

myMap.isMouseOver(item, [distance]) ⇒ boolean ​

Whether the mouse is over a shape, as drawn with toScreen(): inside a polygon, or within distance pixels of a line (default 5) or a point (default 10). Always false while the mouse is outside the canvas. See contains for what you can pass.

Kind: instance method of GeoMap

ParamTypeDescription
itemObject | Array.<LatLon>A polygon, line or point.
[distance]numberFor lines and points, in pixels.

Example

js
for (const country of countries) {
  fill(myMap.isMouseOver(country) ? 'tomato' : 'white');
  beginShape();
  for (const p of myMap.toScreen(country.outer)) vertex(p.x, p.y);
  endShape(CLOSE);
}

Example

js
const p = myMap.toScreen(place);
circle(p.x, p.y, 20);
if (myMap.isMouseOver(place, 10)) text(place.properties.name, p.x + 12, p.y);

myMap.center([lat], [lon]) ⇒ LatLon | GeoMap ​

Gets or sets the center of the map. With no arguments, returns the center. With center(lat, lon), center([lat, lon]) or center({ lat, lon }), moves the map there.

Kind: instance method of GeoMap
Returns: LatLon | GeoMap - The center, or the GeoMap when setting.

ParamType
[lat]number | LatLon | Array.<number>
[lon]number

myMap.zoom([level]) ⇒ number | GeoMap ​

Gets or sets the zoom level. Each step doubles the scale; levels match MapLibre (the whole world is 512 pixels wide at zoom 0).

Kind: instance method of GeoMap
Returns: number | GeoMap - The zoom level (possibly fractional), or the GeoMap when setting.

ParamType
[level]number

myMap.interactive([enabled]) ⇒ boolean | GeoMap ​

Gets or sets whether the map can be dragged and zoomed with the mouse, touch and keyboard. A locked map can still be moved by code (center(), zoom(), flyTo(), fit()), and dragging on the canvas only reaches the sketch, such as mouseDragged(). Use it when the sketch handles the mouse itself; returning false from mousePressed() also stops mouse dragging, with a warning. Has no effect with basemap: false.

Kind: instance method of GeoMap
Returns: boolean | GeoMap - Whether the map is interactive, or the GeoMap when setting.

ParamType
[enabled]boolean

Example

js
// A map that stays put, so dragging draws instead.
myMap = createGeoMap({ center: [35.68, 139.76], zoom: 12, interactive: false });

Example

js
// Press L to lock or unlock the map.
function keyPressed() {
  if (key === 'l') myMap.interactive(!myMap.interactive());
}

myMap.fit(data, [options]) ⇒ GeoMap ​

Centers and zooms so that all of the data is on the canvas.

Kind: instance method of GeoMap

ParamTypeDefaultDescription
data*Anything geoPoints, geoLines or geoPolygons accept or return, or an array of { lat, lon }.
[options]Object
[options.padding]number20Space to leave around the data, in pixels.
[options.maxZoom]number16Upper limit, so a single point isn't zoomed in all the way.

Example

js
countries = geoPolygons(await loadJSON('countries.geojson'));
myMap = createGeoMap({ basemap: false });
myMap.fit(countries);

myMap.flyTo(lat, lon, [zoom]) ⇒ GeoMap ​

Animates to a place. Without a basemap, jumps there immediately.

Kind: instance method of GeoMap

ParamTypeDescription
latnumber
lonnumber
[zoom]numberDefaults to the current zoom level.

myMap.saveCanvas([filename], [extension]) ⇒ Promise.<void> ​

Saves the canvas as an image file with the basemap under it, like p5's saveCanvas() (which would save the sketch alone). Waits for the map to finish loading first, and adds the map's attribution in the bottom-right corner.

Kind: instance method of GeoMap
Returns: Promise.<void> - Resolves once the download has started.

ParamTypeDefaultDescription
[filename]string"'untitled'"The file name, optionally with an extension.
[extension]string"'png'"'png', 'jpg' or 'webp'.

Example

js
function keyPressed() {
  if (key === 's') myMap.saveCanvas('my-map', 'png');
}

myMap.remove() ​

Removes the map and puts the canvas back where it was. Also happens when the sketch's remove() is called.

Kind: instance method of GeoMap

geoPoints(data, [options]) ⇒ Array.<{lat: number, lon: number, properties: Object}> ​

Extracts points from a table, an array of objects, or GeoJSON.

  • p5.Table from loadTable(file, ',', 'header'): the latitude and longitude columns are found by name (lat, latitude, 緯度 / lon, lng, long, longitude, 経度, not case-sensitive). properties holds every column of the row; values that look like numbers become numbers, others (such as "007") stay strings. Rows without a valid latitude and longitude are skipped, with a warning.
  • Array of objects: read the same way as table rows.
  • GeoJSON (FeatureCollection, Feature or geometry): Point and MultiPoint geometries. A MultiPoint gives one item per point, sharing properties.

Kind: global function
Throws:

  • Error If no latitude or longitude column is found, or data is undefined (for example, when the file hasn't loaded yet).
ParamTypeDescription
datap5.Table | Array.<Object> | Object
[options]Object
[options.lat]stringName of the latitude column, if it isn't found automatically.
[options.lon]stringName of the longitude column, if it isn't found automatically.

Example

js
const table = await loadTable('places.csv', ',', 'header');
places = geoPoints(table);
// in draw():
for (const place of places) {
  const p = myMap.toScreen(place);
  circle(p.x, p.y, 10);
}

geoLines(data) ⇒ Array.<{path: Array.<LatLon>, properties: Object}> ​

Extracts lines from GeoJSON: LineString and MultiLineString geometries. A MultiLineString gives one item per line, sharing properties.

Kind: global function

ParamTypeDescription
dataObjectGeoJSON: a FeatureCollection, a Feature or a geometry.

Example

js
for (const line of lines) {
  noFill();
  beginShape();
  for (const p of myMap.toScreen(line.path)) vertex(p.x, p.y);
  endShape();
}

geoPolygons(data) ⇒ Array.<{outer: Array.<LatLon>, holes: Array.<Array.<LatLon>>, properties: Object}> ​

Extracts polygons from GeoJSON: Polygon and MultiPolygon geometries. A MultiPolygon gives one item per polygon, sharing properties. outer is the outline; holes are cut-outs, to draw with beginContour() and endContour().

Kind: global function

ParamTypeDescription
dataObjectGeoJSON: a FeatureCollection, a Feature or a geometry.

Example

js
beginShape();
for (const p of myMap.toScreen(country.outer)) vertex(p.x, p.y);
for (const hole of country.holes) {
  beginContour();
  for (const p of myMap.toScreen(hole)) vertex(p.x, p.y);
  endContour();
}
endShape(CLOSE);

p5.geo ​

The projection and data helpers as plain functions, independent of p5 and MapLibre. Available in sketches as p5.geo. They are strict: every argument must be a number, or they throw a TypeError.

Kind: global namespace

p5.geo.TILE_SIZE : number ​

The width of the world in pixels at zoom 0. MapLibre uses 512, and matching it keeps zoom levels interchangeable.

Kind: static constant of geo

p5.geo.MAX_LATITUDE : number ​

The northern and southern limit of Web Mercator, in degrees. Latitudes beyond it are clamped.

Kind: static constant of geo

p5.geo.STYLES : Object.<string, string> ​

The basemap presets for the basemap option of createGeoMap: keyless OpenFreeMap styles, by name.

Kind: static constant of geo

p5.geo.VERSION : string ​

The version of p5.geo, such as "0.1.2", like p5.VERSION for p5.js. Handy for checking which version a sketch actually loaded, for example when a CDN or browser cache serves an older one.

Kind: static constant of geo
Example

js
console.log(p5.geo.VERSION);

p5.geo.containsLatLon(polygon, lat, lon) ⇒ boolean ​

Whether a latitude and longitude is inside a polygon: inside its outline and outside every hole. Useful for questions about the data itself, such as which country an earthquake was in. Edges are treated as straight lines on the map, as they are drawn.

Polygons crossing the antimeridian need to be split there, as GeoJSON recommends.

Kind: static method of geo

ParamTypeDescription
polygonObject | Array.<LatLon>An item from geoPolygons, or an outline as an array of { lat, lon }.
latnumber
lonnumber

Example

js
const inJapan = p5.geo.containsLatLon(japan, quake.lat, quake.lon);

p5.geo.geoBounds(data) ⇒ Object ​

The bounding box of the data.

Kind: static method of geo
Returns: Object - null if the data is empty.

ParamTypeDescription
data*Anything geoPoints, geoLines or geoPolygons accept or return, or an array of { lat, lon }.

p5.geo.lonToWorldX(lon) ⇒ number ​

Longitude → world units (0 at 180°W to 1 at 180°E).

Kind: static method of geo

ParamType
lonnumber

p5.geo.latToWorldY(lat) ⇒ number ​

Latitude → world units (0 at the northern limit to 1 at the southern limit).

Kind: static method of geo

ParamType
latnumber

p5.geo.worldXToLon(x) ⇒ number ​

World units → longitude.

Kind: static method of geo

ParamType
xnumber

p5.geo.worldYToLat(y) ⇒ number ​

World units → latitude.

Kind: static method of geo

ParamType
ynumber

p5.geo.worldSize(zoom) ⇒ number ​

The width of the world in pixels at a zoom level.

Kind: static method of geo

ParamType
zoomnumber

p5.geo.project(lat, lon, view) ⇒ Object ​

Latitude/longitude → screen position. Uses the copy of the world nearest the center, so a point stays visible wherever the map is panned to (the basemap repeats the world sideways).

Kind: static method of geo

ParamType
latnumber
lonnumber
viewView

p5.geo.projectPath(points, view) ⇒ Array.<{x: number, y: number}> ​

Projects a line or polygon outline as one piece: the whole list moves to the copy of the world nearest the center. Projecting each point separately could tear shapes that straddle the far side of the world.

Kind: static method of geo

ParamType
pointsArray.<LatLon>
viewView

p5.geo.unproject(x, y, view) ⇒ LatLon ​

Screen position → latitude/longitude. Longitude is normalized to -180…180.

Kind: static method of geo

ParamType
xnumber
ynumber
viewView

p5.geo.fitView(bounds, width, height, [options]) ⇒ Object ​

The center and zoom that fit a bounding box on a screen.

Kind: static method of geo

ParamTypeDefaultDescription
boundsObject
widthnumberScreen width in pixels.
heightnumberScreen height in pixels.
[options]Object
[options.padding]number20Space to leave on each side, in pixels.
[options.maxZoom]number16Upper limit for the zoom.

LatLon : Object ​

A latitude and longitude, in degrees.

Kind: global typedef
Properties

NameTypeDescription
latnumberLatitude, from -90 (south) to 90 (north).
lonnumberLongitude, from -180 (west) to 180 (east).

View : Object ​

What a map shows: its center sits in the middle of a width × height screen.

Kind: global typedef
Properties

NameTypeDescription
latnumberLatitude of the center.
lonnumberLongitude of the center.
zoomnumberZoom level.
widthnumberScreen width in pixels.
heightnumberScreen height in pixels.

Passing numbers and strings ​

GeoMap methods and the createGeoMap() options are forgiving, so that values read from a file can go straight in:

  • Numeric strings become numbers. myMap.toScreen('35.6586', '139.7454') works the same as with numbers, so table.getString() results can be passed directly. This applies to toScreen, fromScreen, center, zoom, flyTo, the fit options, and the center and zoom options of createGeoMap().
  • Other values become NaN, with a warning. An empty string, null, undefined or text such as 'abc' gives NaN and a console message naming the function and the argument, for example p5.geo: toScreen() expected a number for lat, but got "abc". Each function and argument warns only once, so a mistake inside draw() doesn't flood the console. Empty values are never treated as 0.
  • They never throw.

The functions in p5.geo are strict instead: every argument must be a number, or they throw a TypeError naming the function and the argument. NaN counts as a number and passes through.

For bundlers and TypeScript, see Using with a bundler.

Released under the MIT License. Map data © OpenStreetMap contributors, basemaps by OpenFreeMap.