Skip to content

Rulers

Rulers render timeline timestamps and frequency axes that stay in sync with spectrogram and waveform viewports.

Tick intervals recalculate automatically as you zoom and pan. When connected to navigation, dragging directly on a ruler scrubs across time or adjusts visible frequency bounds.

Rulers attach to standard HTML <canvas> elements. Calling createTimeRuler or createFrequencyRuler without options applies standard tick marks, labels, and auto-resizing:

import { Sonoscope } from "@sonoscope/core";
const scope = await Sonoscope.fromUrl("/audio/sample.wav");
// Create a horizontal time ruler using default options
const timeRuler = scope.createTimeRuler(timeCanvas);
// Create a vertical frequency ruler using default options
const freqRuler = scope.createFrequencyRuler(freqCanvas);
// Synchronize drag and zoom interactions
scope.attachNavigation(timeCanvas, { axis: "time" });
scope.attachNavigation(freqCanvas, { axis: "frequency" });

Set visible time and frequency ranges on Sonoscope, not on a ruler:

const scope = await Sonoscope.fromUrl("/audio/sample.wav", {
startTime: 5,
endTime: 15,
minDuration: 0.05,
maxDuration: 30,
minFrequency: 100,
maxFrequency: 12_000,
});

Draws top tick marks with dynamic major and minor subdivisions:

scope.createTimeRuler(timeCanvas);

Applies custom theme colors:

scope.createTimeRuler(timeCanvas, {
color: "#38bdf8",
});

Positions tick marks below the numeric timestamp labels:

scope.createTimeRuler(timeCanvas, {
tickPosition: "bottom",
});

Draws tick marks along both the top and bottom borders:

scope.createTimeRuler(timeCanvas, {
tickPosition: "both",
});

Replaces standard tick lines with segmented blocks:

scope.createTimeRuler(timeCanvas, {
renderer: "boxes",
});

Formats timestamps in standard media timecode notation:

scope.createTimeRuler(timeCanvas, {
timeFormat: "timecode",
});

Displays vertical frequency values formatted in kilohertz:

scope.createFrequencyRuler(freqCanvas, {
frequencyFormat: "khz",
});

Options accepted by scope.createTimeRuler(canvas, options). Full reference: TimeRulerConfig.

OptionTypeDefaultDescription
autoRenderoptbooleantrueWhether to automatically re-render when viewport or configuration changes.
coloroptstring"#a0a0a0"Primary color for axis lines, tick marks, and text labels.
backgroundColoroptstring"transparent"Canvas background fill color.
tickColoroptstringcolorSpecific color override for tick lines.
labelColoroptstringcolorSpecific color override for text labels.
fontoptstring"10px monospace"CSS font specification for time labels.
tickPositionopt"top" | "bottom" | "both" | "inside""top"Tick mark position relative to the ruler baseline.
timeFormatoptTimeFormatMode"auto"Numeric timestamp formatting mode. - "auto": Adapts precision based on zoom level. - "seconds": Displays raw seconds (e.g., `12.5s`). - "timecode": Broadcast notation (`mm:ss.ms`). - "hhmmss": Clock time (`hh:mm:ss`). - Custom function `(sec: number) => string`.
minMajorPixelSpacingoptnumber75Minimum pixel spacing between adjacent major tick labels.
rendereroptTimeRulerRendererName | TimeRulerRenderer"ticks"Visual renderer: standard tick lines or segmented boxes.
autoResizeoptbooleantrueWhether to automatically resize canvas pixel resolution when container dimensions change.
devicePixelRatiooptboolean | numberwindow.devicePixelRatioDevice pixel ratio scaling factor for HiDPI/Retina displays.

Options accepted by scope.createFrequencyRuler(canvas, options). Full reference: FrequencyRulerConfig.

OptionTypeDefaultDescription
autoRenderoptbooleantrueWhether to automatically re-render when viewport or configuration changes.
frequencyScaleoptFrequencyScaleinherits from Sonoscope viewport scaleFrequency scale mapping: linear, mel, or logarithmic.
coloroptstring"#a0a0a0"Primary color for axis lines, tick marks, and text labels.
backgroundColoroptstring"transparent"Canvas background fill color.
tickColoroptstringcolorSpecific color override for tick lines.
labelColoroptstringcolorSpecific color override for text labels.
fontoptstring"10px monospace"CSS font specification for frequency labels.
tickPositionopt"left" | "right" | "both" | "inside""left"Tick mark position relative to the vertical ruler axis.
frequencyFormatoptFrequencyFormatMode"auto"Frequency label formatting mode. - "auto": Switches between Hz and kHz depending on magnitude. - "hz": Always formats in Hertz (e.g. `2000 Hz`). - "khz": Always formats in kilohertz (e.g. `2.0 kHz`). - Custom function `(hz: number) => string`.
minMajorPixelSpacingoptnumber45Minimum pixel spacing between adjacent major frequency labels.
rendereroptFrequencyRulerRendererName | FrequencyRulerRenderer"ticks"Visual renderer: standard tick lines or segmented boxes.
autoResizeoptbooleantrueWhether to automatically resize canvas pixel resolution when container dimensions change.
devicePixelRatiooptboolean | numberwindow.devicePixelRatioDevice pixel ratio scaling factor for HiDPI/Retina displays.

Use scope.attachNavigation(canvas, options) to link panning and zooming between rulers and spectrograms:

  • Axis constraints: Set { axis: 'time' } on horizontal rulers and { axis: 'frequency' } on vertical rulers so dragging only navigates along that ruler’s dimension.
  • Drag & scroll: Dragging scrubs the timeline or frequency range; scrolling or pinching zooms in and out.
  • Synchronized views: Navigating on any attached canvas immediately updates all connected rulers and spectrogram views.

Play around with the code in the live sandbox below:

  • Drag the spectrogram or rulers to pan around.
  • Scroll / Pinch over the rulers to zoom in and out.
  • Edit the options in index.ts to see how different tick styles, positions, and formats look in real time.