Skip to content
OVEX TECH
Education & E-Learning

Load Images and Data with p5.js 2.0 Effortlessly

Load Images and Data with p5.js 2.0 Effortlessly

Load Images and Data with p5.js 2.0 Effortlessly

This guide will walk you through the process of loading various types of data, such as images and JSON files, into your p5.js sketches using version 2.0. You will learn how to properly handle asynchronous loading operations, display loaded images, fetch data from APIs, and implement strategies for managing loading states and optimizing performance.

Prerequisites

  • Basic understanding of p5.js
  • Familiarity with the p5.js Web Editor
  • (Optional) Basic knowledge of JavaScript Promises, async, and await

Step 1: Uploading Your Assets

Before you can load any files into your p5.js sketch, you need to upload them to your project. This is particularly important for local files like images.

  1. Open your p5.js sketch in the p5.js Web Editor.
  2. In the top-left corner, click the arrow icon to open the sketch files navigation pane.
  3. Click the ‘+’ symbol to upload a file.
  4. Drag and drop your image file (e.g., a .jpg, .png) from your computer into the navigation pane.
  5. The file will appear in the list. You can click on it to verify it has been uploaded correctly.

Step 2: Loading an Image with loadImage()

p5.js version 2.0 introduces asynchronous loading for many functions, including loadImage(). This means you need to use async and await to handle the loading process correctly.

  1. Declare a global variable to store your image. For example: let img;
  2. In your setup() function, you need to make it an async function. This tells JavaScript that it will contain operations that might take time to complete.

    async function setup() { ... }

  3. Inside the async setup() function, call loadImage() with the name of your uploaded image file. Use the await keyword before loadImage(). This pauses the execution of setup() until the image is fully loaded and then assigns the loaded image to your global variable.

    img = await loadImage('your-image-name.jpg');

  4. In your draw() function, you can now display the image using the image() function:

    image(img, 0, 0);

Common Mistakes and How to Fix Them

  • Forgetting async: If you use await without marking your function as async, you’ll get an error like ‘await is only valid in async function‘. Simply add async before function setup().
  • Forgetting await: If you forget await before loadImage(), your variable will store a Promise object, not the actual image. You cannot draw a Promise. This will likely result in a blank canvas or an error. p5.js often provides a helpful error message suggesting you add ‘await‘.

Step 3: Loading JSON Data with loadJSON()

Similar to images, JSON data (often fetched from APIs or local files) is loaded asynchronously. The process is almost identical to loading an image.

  1. Declare a global variable to hold your JSON data: let jsonData;
  2. Ensure your setup() function is marked with async.
  3. Use await loadJSON() with the URL of the JSON resource or the path to your local JSON file. Assign the result to your variable.

    jsonData = await loadJSON('https://api.example.com/data.json');

    or

    jsonData = await loadJSON('data.json');

  4. Once loaded, you can access the data within your jsonData variable. For example, if your JSON has a ‘message’ property:

    console.log(jsonData.message);

Example: Fetching a Dog Image from an API

This demonstrates fetching a URL for a dog image from an API and then loading that image.

  1. Define global variables for the image and the JSON data: let dogImage;, let dogApiData;
  2. Make setup() asynchronous.
  3. Load the JSON data from the Dog API:

    dogApiData = await loadJSON('https://dog.ceo/api/breeds/image/random');

  4. Use the URL from the loaded JSON to load the actual image:

    dogImage = await loadImage(dogApiData.message);

  5. In draw(), display the loaded dog image:

    image(dogImage, 0, 0, width, height);

Step 4: Handling Loading Progress and Multiple Assets

When loading many assets or dealing with potentially slow network requests, it’s good practice to provide feedback to the user and manage the loading process efficiently.

Strategy 1: Loading in setup() with a Loading Indicator

If you want draw() to start immediately, even before all assets are loaded, you can move the loading logic out of setup() into a separate asynchronous function.

  1. Create a boolean variable to track if data is loaded, initialized to false: let dataLoaded = false;
  2. Define a new async function, e.g., async function loadAssets() { ... }.
  3. Place all your await loadImage() or await loadJSON() calls inside this loadAssets() function.
  4. At the end of loadAssets(), set dataLoaded = true;.
  5. In your regular (non-async) setup() function, call loadAssets();. Note that you do NOT use await here, so setup() finishes quickly, and draw() begins executing.
  6. In your draw() function:
    • Check the value of dataLoaded.
    • If false, draw a loading indicator (e.g., a progress bar, a spinning circle, or text like “Loading…”).
    • If true, draw your actual sketch content.

Creating a Simple Loading Bar

You can make the loading bar dynamic by mapping its width to the progress of loading assets.

  1. If loading multiple items into an array (e.g., let images = [];), you can track the array’s length.

    Inside loadAssets(), after each successful load, push the item into the array: images.push(loadedItem);

  2. In draw(), calculate the width of the loading bar based on how many items are loaded:

    let numLoaded = images.length;

    let totalItems = 20; // The total number of items you expect to load

    let barWidth = map(numLoaded, 0, totalItems, 0, width);

    fill(0); // Black color for the bar

    rect(0, 0, barWidth, 20); // Draw the loading bar at the top

  3. Add noLoop(); in setup() if you only want draw() to run once after loading, or manage looping appropriately if you want animations during loading.

Strategy 2: Parallel Loading with Promise.all()

For maximum efficiency when loading multiple assets, you can start all loading operations simultaneously and then wait for all of them to complete.

  1. Create an array to store the Promises returned by the loading functions, e.g., let promises = [];
  2. In your async loading function (e.g., loadAssets()), loop through your assets and push the Promise (the result of loadImage() or loadJSON() *without* await) into the promises array.

    for (let i = 0; i < 5; i++) {

    promises.push(loadImage('kitten' + i + '.png'));

    }

  3. After the loop, use Promise.all(promises). This function takes an array of Promises and returns a new Promise that resolves when all the input Promises have resolved. You must use await with Promise.all().

    let loadedImages = await Promise.all(promises);

  4. The loadedImages variable will be an array containing all the successfully loaded assets in the same order as the original promises.

    // Now loadedImages[0] is the first image, loadedImages[1] is the second, etc.

Expert Note on Efficiency

Loading assets one by one using await in a loop is simpler but can be slower because each asset must finish loading before the next one starts. Using Promise.all() allows multiple assets to download concurrently, significantly speeding up the loading process, especially for many assets.

Important Considerations

  • API Limits: Be mindful of how many requests you send to an API. Flooding an API with too many requests can lead to errors or temporary bans.
  • Error Handling: The examples above do not include explicit error handling. In a real application, you should implement mechanisms to catch errors during loading (e.g., using try...catch blocks with async/await) and provide user feedback or alternative actions if an asset fails to load.
  • p5.js Version: Ensure you are using p5.js version 2.0 or later for these async/await patterns to work correctly. Older versions (like 1.x) handle loading differently, often using callback functions.

Source: How to Load Data with p5.js (2.0) (YouTube)

Leave a Reply

Your email address will not be published. Required fields are marked *

Written by

John Digweed

1,377 articles

Life-long learner.