Displays Tutorial

ProControls for p5.js — by David Stein
VUMeter, VUDial, LEDMeter, ADSRDisplay, Markup, ConsolePanel, TimeGraphPanel, StatusPanel — all examples live and editable
↗ Full Docs
Welcome! This tutorial covers the read-only display controls in ProControls — meters, graphs, rich text, and logging panels. These controls do not take user input; instead, you update them from your sketch code to visualize data in real time. Every code block on this page is live and editable — click inside a code block, make a change, and the preview updates automatically.
First time here? Before running these examples in your own project, visit the Getting Started page for the HTML setup and script tags you need to load ProControls.
VUMeter VUDial LEDMeter ADSRDisplay Markup ConsolePanel TimeGraphPanel StatusPanel ListView GridView HeatMapView

VUMeter

Level Meter

A VUMeter is a vertical bar meter — the kind you see on a mixing console or audio interface. The bar rises and falls to show a signal level in real time. You drive it from your sketch code by setting its value property (0–1 by default) in your draw() loop.

Step 1 Your first VU meter

Create a VUMeter with no options and it appears at a sensible default size. The value property controls how high the bar is — 0 is empty, 1 is full. The example below animates the level using sin() so you can see it move.

editable — changes update the preview
Auto-placement: When you leave out x and y, ProControls places the control automatically so it does not overlap others.
Step 2 Customizing the meter

Use label to add a text label, peak to show a hanging peak indicator dot that falls slowly after the signal drops, and segments to split the bar into discrete blocks (like a classic LED meter). Try changing these!

editable — try changing segments or removing peak
Step 3 Setting the danger zone

Use warnAt to set where the bar turns yellow, and dangerAt to set where it turns red — both as fractions of 0–1. This lets you mark the "safe zone," the "caution zone," and the "clip zone" visually, just like a real mixing board.

editable — try adjusting warnAt and dangerAt
Step 4 Stereo meters side by side

Creating two VUMeters next to each other makes a classic stereo pair. Give each one an explicit x and y so they sit side by side. Drive them independently for a true left/right display.

editable — try making the left and right signals different

VUDial

Circular Meter

A VUDial is a circular level indicator — like the large needle meters on vintage studio gear. An arc sweeps from low to high as the value increases. Set value from your draw() loop just like VUMeter.

Step 1 Your first VU dial

A one-liner creates a circular meter. The arc sweeps around the dial as the value changes. Watch the arc respond to the animated value below.

editable — changes update the preview
Step 2 Customizing the dial

The size option controls the diameter. You can add a label, set warnAt and dangerAt thresholds for color changes, and show a numeric readout with readout: 'raw'.

editable — try changing size, warnAt, or dangerAt
Step 3 Custom min and max

By default the dial goes from 0 to 1, but you can set min and max to any range — for example, decibels from −60 to 0. The readout will show the mapped value, not the raw 0–1 fraction.

editable — try changing min, max, or the value formula
Step 4 Updating from audio analysis

In a real project you would drive the meter from audio analysis or a sensor reading. Here we simulate a signal with noise to show how a responsive meter looks. Use smoothing (0–1) to add ballistic lag so the needle does not jump instantly.

editable — try changing the smoothing value
Tip: smoothing is available on both VUMeter and VUDial. A value around 0.8–0.9 gives the classic "needle ballistics" feel of analog meters.

LEDMeter

LED Bar

A LEDMeter is a horizontal bar of discrete LED segments — the kind of level meter you see on a guitar tuner or effects pedal. Unlike VUMeter, it always displays as distinct blocks and is usually wider than it is tall.

Step 1 Your first LED meter

A one-liner creates a horizontal bar of LED segments. Set value (0–1) from your sketch to light up segments from left to right.

editable — changes update the preview
Step 2 Setting segments and size

Use segments to control how many LEDs the bar is divided into. More segments means finer resolution. The width and height options control the overall size of the bar.

editable — try changing segments or the bar size
Step 3 Multiple meters stacked

Stack several LEDMeters vertically to create a channel strip or a multi-band display. Position them with explicit y values so they line up neatly.

editable — try adding a third bar or changing the speeds
Step 4 Driving from a real value

In practice you feed the LEDMeter from a computed number — the amplitude of an audio signal, the speed of a physics object, or anything that changes over time. Here a ConsolePanel shows the raw value alongside the meter.

editable — watch the value in the console as you change the formula

ADSRDisplay

Envelope Viewer

An ADSRDisplay draws an Attack–Decay–Sustain–Release envelope shape — the classic four-parameter curve used in synthesizers to shape how a sound evolves over time. It is a read-only visual; pair it with four dials or sliders to let the user edit the envelope values.

Step 1 Your first ADSR display

Create an ADSRDisplay with default values and it shows a classic envelope shape. The four properties are attack, decay, sustain, and release — all 0–1 fractions of their maximum time.

editable — changes update the preview
Step 2 Sizing and labeling

Set width and height to fit the display in your layout. The label option adds a title. The curve automatically fills the available space.

editable — try changing the ADSR values
Step 3 Connecting to dials

The classic use case: four dials control the ADSR shape. In the onChange of each dial, update the matching property on the ADSRDisplay. The display redraws automatically.

editable — turn the knobs and watch the envelope update
Step 4 Animating the envelope

You can update the ADSR properties from anywhere in your sketch — not just from a dial callback. Here the sustain level pulses slowly to show how the display responds to programmatic changes.

editable — try animating attack or release instead

Markup

Rich Text Panel

A Markup control displays styled text — paragraphs, bold, italic, links, and separators — rendered on the canvas. Use it for help text, status readouts, or any formatted copy that belongs inside your ProControls layout.

Step 1 Your first markup panel

Pass a string to the text option. Plain text is displayed as-is. The panel auto-sizes to fit its content.

editable — changes update the preview
Step 2 Formatting — bold, italic, and separators

Wrap text in **double asterisks** for bold and *single asterisks* for italic. A line containing only --- becomes a horizontal rule that separates sections.

editable — try adding more bold or italic spans
Step 3 Links and click callbacks

Add a link with [label](url) syntax. Clicking a link opens the URL in a new tab by default. You can override this with the onClick(href) callback to handle the link yourself.

editable — try clicking the link in the preview
Step 4 Updating text dynamically

Set the text property at any time to update what the Markup panel displays. This is useful for status readouts that should update as your sketch runs — for example, showing the current frame rate or a sensor value.

editable — watch the values update in the preview
Tip: For short status lines that change every frame, update text only every few frames (e.g. frameCount % 10 === 0) to avoid unnecessary redraws.

ConsolePanel

Log Output

A ConsolePanel displays text log output directly on the canvas — replacing console.log() output that would otherwise only appear in the browser's developer tools. New lines appear at the bottom and scroll up as the panel fills.

Step 1 Your first console panel

Create a ConsolePanel and then call console.log() anywhere in your sketch. ProControls intercepts the call and shows the output in the panel. You can still see the output in the browser console too.

editable — changes update the preview
Step 2 Sizing and options

Set width and height to control the panel size. The maxLines option caps how many lines are kept before older ones are dropped. You can also set movable: false to lock the panel in place so users cannot drag it around.

editable — try changing maxLines or width
Step 3 Logging from interactions

The most common pattern is to log values in onChange callbacks so you can see what a control is doing as you interact with it. The ConsolePanel gives you that feedback without switching to the browser's developer tools.

editable — drag the slider and watch the log update
Step 4 Clearing and controlling the log

Call console.clear() to empty the panel, or use log.clear() directly on the ConsolePanel instance. Logging from draw() works, but throttle it (e.g., every 15 frames) so the panel does not scroll too fast to read.

editable — watch the running counter in the panel

TimeGraphPanel

Time-Series Graph

A TimeGraphPanel draws a scrolling time-series graph — like an oscilloscope or a heart-rate monitor. Push new data points with push(value) and the graph scrolls left to show the history. You can plot multiple series on the same panel in different colors.

Step 1 Your first time graph

Create a TimeGraphPanel, then call push(value) every frame (or as often as you have new data). The graph auto-scales to fit the values you push.

editable — changes update the preview
Step 2 Customizing the graph

Set min and max to fix the vertical range (instead of auto-scaling). The gridLines option draws horizontal reference lines, and label adds a title to the panel.

editable — try removing min/max to see auto-scaling
Step 3 Multiple series

Push data to named series to plot several lines on the same graph. Pass an object to push() where each key is a series name and the value is the new data point. Each series gets its own color automatically.

editable — try adding a third series
Step 4 Graphing control values in real time

A TimeGraphPanel paired with a control lets you visualize how a value changes as the user interacts. Drag the slider below and watch your movements recorded in the graph as a live trace.

editable — drag the slider and watch the graph trace
Tip: Call graph.clear() to reset all series, or set graph.history (number of data points to keep) to control how far back the graph scrolls.
Step 5 Custom timestamps

By default each push() call is stamped with the current wall-clock time. You can override this by including a time field (in seconds) in the data object. This lets you replay pre-recorded data at the correct positions, graph sporadic events that don't arrive every frame, or synchronize multiple graphs to a shared timeline.

editable — try changing the time values
Tip: For live data that doesn't arrive every frame, use { time: millis() / 1000, value: v } so the X axis reflects the actual elapsed time between samples rather than frame count.

StatusPanel

Performance Monitor

A StatusPanel is a real-time performance meter showing frame rate, frame time, control count, and JavaScript heap memory. It's perfect for monitoring your sketch during development — spot performance bottlenecks, watch how many controls you've created, and ensure your draw loop stays responsive at 60 FPS.

Step 1 Your first StatusPanel

Create a StatusPanel with no options — it anchors to the bottom of the canvas by default and shows live FPS, frame time (Δt in milliseconds), active control count, and available heap memory.

editable — panel updates every frame
Step 2 Position it manually

Provide x and y to place the panel anywhere on the canvas. Set width and height to control its size. When you specify position, it no longer auto-resizes with the canvas.

editable — try different x, y, width, height values
Step 3 Monitoring sketch performance

The Δt (delta time) metric shows average frame time in milliseconds. For 60 FPS, target is ~16.67ms. If Δt turns red and climbs above that, your draw() loop or event handlers are doing heavy work. Watch the Controls counter — it increments with each control you add.

editable — add more controls and watch the counter
Step 4 Toggle visibility at runtime

Set status.visible = false to hide the panel without destroying it. Turn it back on with status.visible = true. This is useful for hiding debug overlays in production code or toggling the monitor on demand.

editable — change visible to false to hide it
Tip: StatusPanel is invisible by default and consumes minimal resources when hidden. It's safe to leave in production code and toggle on with status.visible = true for debugging when needed.

ListView

Scrollable List

A ListView displays a scrollable list of strings. Click any item to select it; use the scroll wheel or scrollbar to navigate. The onSelect callback fires when a row is clicked, passing the item and its index.

editable — changes update the preview
Tip: Assign a new array to lv.items to update the list. Use lv.selectedIdx to get or set the selection programmatically.

GridView

Scrollable Table

A GridView displays a scrollable table where each row is an object with named fields. Column widths are automatically computed from the header names and cell values. The header row stays fixed at the top (no vertical scroll). Horizontal scrolling is available when columns exceed the panel width. Click a row to select it.

editable — changes update the preview
Tip: Reassign gv.items with new data to update the grid. Column headers are automatically derived from the object keys. Use gv.scrollX and gv.scrollY to programmatically control scrolling.

HeatMapView

Hierarchical Heatmap

A HeatMapView displays a grid of colored cells representing hierarchical data grouped by multiple dimensions. Each cell's color intensity reflects the magnitude of its aggregated value. Click any cell to drill down one level; use breadcrumbs at the top to jump back to earlier drill levels, or right-click to pop back one level. When you reach the deepest dimension, clicking a cell fires the onSelect callback with the full drill path.

editable — click to drill, right-click to go back
Tip: The fields array defines the drill-down hierarchy. Start with product, then brand, then trim. The valueField specifies which property to sum at each level. Reassign hm.items with new data to update the heatmap. Use the breadcrumb bar to navigate, or right-click any cell to pop back one level.