Visualization Components
This document covers OMD's SVG visualization components. Each component is instantiated and loaded via loadFromJSON, then passed to omdDisplay or omdCanvas for rendering.
import { omdNumberLine, omdDisplay } from '@teachinglab/omd';
const display = new omdDisplay(document.getElementById('container'));
const line = new omdNumberLine();
line.loadFromJSON({ min: 0, max: 10, increment: 1, dotValues: [3, 7] });
display.load(line);
numberLine
Renders a horizontal number line with optional dots, labels, and arrows.
Example JSON
{ "omdType": "numberLine", "min": 0, "max": 20, "increment": 2, "dotValues": [6, 14], "title": "Miles walked" }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
min |
number | Yes | — | Left bound of the number line |
max |
number | Yes | — | Right bound of the number line |
increment |
number | Yes | — | Spacing between tick marks |
dotValues |
number[] | No | [] |
Values at which to place dots |
title |
string | No | "" |
Title text rendered above the line |
label |
string | No | "" |
Label rendered beside the line |
units |
string | No | "" |
Unit label appended to tick numbers |
showLeftArrow |
boolean | No | false |
Show an arrow on the left end |
showRightArrow |
boolean | No | false |
Show an arrow on the right end |
hideDefaultNumbers |
boolean | No | false |
Hide the default tick number labels |
specialNumbers |
object[] | No | [] |
Custom labels at specific positions: {value, label} |
totalWidth |
number | No | auto | Total SVG width in px |
Example
const line = new omdNumberLine();
line.loadFromJSON({
min: 0,
max: 20,
increment: 2,
dotValues: [6, 14],
showRightArrow: true,
title: 'Temperature (°C)',
specialNumbers: [{ value: 6, label: 'low' }, { value: 14, label: 'high' }]
});
display.load(line);
doubleNumberLine
Renders two aligned number lines stacked vertically, useful for ratio and rate comparisons.
Example JSON
{ "omdType": "doubleNumberLine", "topNumberLine": { "min": 0, "max": 5, "increment": 1, "title": "Hours" }, "bottomNumberLine": { "min": 0, "max": 60, "increment": 12, "title": "Minutes" } }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
topNumberLine |
object | Yes | — | Config for the top number line (same fields as numberLine) |
bottomNumberLine |
object | Yes | — | Config for the bottom number line |
spacing |
number | No | auto | Vertical gap in px between the two lines |
Example
const dbl = new omdDoubleNumberLine();
dbl.loadFromJSON({
topNumberLine: { min: 0, max: 5, increment: 1, title: 'Hours' },
bottomNumberLine: { min: 0, max: 60, increment: 12, title: 'Minutes' },
spacing: 20
});
display.load(dbl);
balanceHanger
Renders a balance scale hanger. Variables (e.g. 'x') are drawn as pill shapes; numbers as rectangles.
Example JSON
{ "omdType": "balanceHanger", "leftValues": ["x", "x", "x"], "rightValues": ["1", "1", "1", "1", "1", "1"], "tilt": "none" }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
leftValues |
string[] | Yes | — | Tokens on the left side, e.g. ['x', 'x', '3'] |
rightValues |
string[] | Yes | — | Tokens on the right side |
tilt |
'none'|'left'|'right' |
No | 'none' |
Direction the beam tilts |
fontFamily |
string | No | system | Font for tile labels |
fontSize |
number | No | auto | Font size in px |
backgroundColor |
string | No | "" |
Background fill color |
backgroundCornerRadius |
number | No | 0 |
Corner radius of the background rect |
backgroundOpacity |
number | No | 1 |
Opacity of the background rect |
showBackground |
boolean | No | false |
Whether to render a background rect |
Example
const hanger = new omdBalanceHanger();
hanger.loadFromJSON({
leftValues: ['x', 'x', 'x'],
rightValues: ['1', '1', '1', '1', '1', '1'],
tilt: 'none'
});
display.load(hanger);
tapeDiagram
Renders a horizontal segmented tape diagram. Each segment can be a plain value or a full object controlling color, label, and weight.
Example JSON
{ "omdType": "tapeDiagram", "title": "Parts of 24", "values": [{ "value": 8, "color": "#4A90D9", "label": "A" }, { "value": 8, "color": "#7ED321", "label": "B" }, { "value": 8, "color": "#F5A623", "label": "C" }], "labelSet": { "braces": [{ "startIndex": 0, "endIndex": 2, "label": "24", "showBelow": true }] } }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
values |
array | Yes | — | Segments. Each entry is a string/number or {value, weight, showLabel, color, textColor, label} |
totalWidth |
number | No | auto | Total width of the tape in px |
title |
string | No | "" |
Title above the tape |
titleFontSize |
number | No | auto | Font size for the title |
titleColor |
string | No | "" |
Color for the title text |
segmentHeight |
number | No | auto | Height of each segment in px |
segmentCornerRadius |
number | No | 0 |
Corner radius of segments |
segmentStrokeColor |
string | No | "" |
Stroke color for segment borders |
segmentStrokeWidth |
number | No | 1 |
Stroke width for segment borders |
labelFontSize |
number | No | auto | Font size for segment labels |
segmentTextColor |
string | No | "" |
Default text color for segment labels |
braceLabelFontSize |
number | No | auto | Font size for brace labels |
braceColor |
string | No | "" |
Color for brace strokes |
labelSet |
object | No | {} |
Brace annotations: { braces: [{startIndex, endIndex, label, showBelow, color, fontSize, strokeWidth}] } |
Example
const tape = new omdTapeDiagram();
tape.loadFromJSON({
title: 'Parts of 24',
values: [
{ value: 8, color: '#4A90D9', label: 'A' },
{ value: 8, color: '#7ED321', label: 'B' },
{ value: 8, color: '#F5A623', label: 'C' }
],
labelSet: {
braces: [{ startIndex: 0, endIndex: 2, label: '24', showBelow: true }]
}
});
display.load(tape);
doubleTapeDiagram
Renders two tape diagrams stacked vertically, useful for part-to-part or part-to-whole comparisons.
Example JSON
{ "omdType": "doubleTapeDiagram", "topTapeDiagram": { "values": [{ "value": 3, "color": "#4A90D9" }, { "value": 3, "color": "#4A90D9" }, { "value": 3, "color": "#4A90D9" }], "title": "Miles" }, "bottomTapeDiagram": { "values": [{ "value": 15, "color": "#F5A623" }], "title": "Total" } }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
topTapeDiagram |
object | Yes | — | Config for the top tape (same fields as tapeDiagram) |
bottomTapeDiagram |
object | Yes | — | Config for the bottom tape |
spacing |
number | No | auto | Vertical gap in px between the two tapes |
Example
const dbl = new omdDoubleTapeDiagram();
dbl.loadFromJSON({
topTapeDiagram: {
values: [{ value: 3, color: '#4A90D9' }, { value: 3, color: '#4A90D9' }, { value: 3, color: '#4A90D9' }],
title: 'Miles'
},
bottomTapeDiagram: {
values: [{ value: 15, color: '#F5A623' }],
title: 'Total'
},
spacing: 16
});
display.load(dbl);
coordinatePlane
Renders a Cartesian coordinate plane. Supports graphing equations, line segments, points, and interactive sliders.
Example JSON
{ "omdType": "coordinatePlane", "xMin": -5, "xMax": 5, "yMin": -5, "yMax": 5, "graphEquations": [{ "equation": "y = 2x + 1", "color": "#E74C3C", "strokeWidth": 2 }], "dotValues": [[0, 1, "#E74C3C"]] }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
xMin |
number | Yes | — | Left bound of the x-axis |
xMax |
number | Yes | — | Right bound of the x-axis |
yMin |
number | Yes | — | Bottom bound of the y-axis |
yMax |
number | Yes | — | Top bound of the y-axis |
xLabel |
string | No | "x" |
Label for the x-axis |
yLabel |
string | No | "y" |
Label for the y-axis |
tickInterval |
number | No | 1 |
Spacing between tick marks |
showTickLabels |
boolean | No | true |
Show numeric tick labels |
showBackground |
boolean | No | false |
Render a background rect |
interactive |
boolean | No | false |
Render variable sliders when true |
size |
'small'|'medium'|'large' |
No | 'medium' |
Preset size of the plane |
graphEquations |
object[] | No | [] |
Equations to plot: {equation, color, strokeWidth} |
lineSegments |
object[] | No | [] |
Segments to draw: {point1: [x,y], point2: [x,y], color} |
dotValues |
array[] | No | [] |
Points to mark: each entry is [x, y, 'color'] |
variables |
object[] | No | [] |
Interactive slider definitions: {name, value, min, max, step} |
shapeSet |
object | No | {} |
Additional shapes to overlay |
graphPadding |
number | No | auto | Internal padding around the graphing area |
backgroundColor |
string | No | "" |
Background fill color |
backgroundCornerRadius |
number | No | 0 |
Corner radius of the background rect |
backgroundOpacity |
number | No | 1 |
Opacity of the background rect |
Example
const plane = new omdCoordinatePlane();
plane.loadFromJSON({
xMin: -5, xMax: 5,
yMin: -5, yMax: 5,
graphEquations: [
{ equation: 'y = 2x + 1', color: '#E74C3C', strokeWidth: 2 }
],
dotValues: [[0, 1, '#E74C3C'], [2, 5, '#3498DB']],
size: 'medium'
});
display.load(plane);
Interactive example (with sliders):
plane.loadFromJSON({
xMin: -10, xMax: 10,
yMin: -10, yMax: 10,
interactive: true,
variables: [{ name: 'm', value: 1, min: -5, max: 5, step: 0.5 }],
graphEquations: [{ equation: 'y = m*x', color: '#2ECC71' }]
});
tileEquation
Renders an algebra tile equation. Token values: 'x', '-x', 'y', '-y', '1', '-1'.
Example JSON
{ "omdType": "tileEquation", "left": ["x", "x", "1", "1", "1"], "right": ["1", "1", "1", "1", "1", "1", "1"], "tileSize": 40 }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
equation |
string | No | "" |
Equation string parsed into tiles (e.g. 'x + 1 = -x + 3') |
left |
string[] | No | [] |
Explicit left-side token array |
right |
string[] | No | [] |
Explicit right-side token array |
tileSize |
number | No | auto | Size of each tile in px |
tileGap |
number | No | auto | Gap between tiles in px |
equalGap |
number | No | auto | Gap around the equals sign |
tileRadius |
number | No | auto | Corner radius of tiles |
showLabels |
boolean | No | true |
Show variable/number labels on tiles |
fontFamily |
string | No | system | Font for tile labels |
fontSize |
number | No | auto | Font size for tile labels |
plusColor |
string | No | "" |
Color for positive tiles |
equalsColor |
string | No | "" |
Color for the equals sign |
xPillColor |
string | No | "" |
Color for variable pill tiles |
Example
const tiles = new omdTileEquation();
tiles.loadFromJSON({
left: ['x', 'x', '1', '1', '1'],
right: ['1', '1', '1', '1', '1', '1', '1'],
tileSize: 40
});
display.load(tiles);
table
Renders a value table. Can auto-generate rows from an equation or use manually provided data.
Example JSON
{ "omdType": "table", "equation": "y=3x+2", "xMin": 0, "xMax": 5, "stepSize": 1, "headers": ["x", "y"], "alternatingRowColors": true }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
equation |
string | No* | "" |
Equation to generate rows (e.g. 'y=2x'). Required unless data is provided. |
data |
array[][] | No* | [] |
Manual rows as [[x, y], ...]. Used when equation is not set. |
headers |
string[] | No | auto | Column header labels |
xMin |
number | No | 0 |
First x value (when using equation) |
xMax |
number | No | 5 |
Last x value (when using equation) |
stepSize |
number | No | 1 |
Step between x values |
title |
string | No | "" |
Title above the table |
alternatingRowColors |
boolean | No | false |
Shade alternating rows |
fontSize |
number | No | auto | Font size for cell text |
headerFontSize |
number | No | auto | Font size for header text |
fontFamily |
string | No | system | Font for cell text |
headerFontFamily |
string | No | system | Font for header text |
cellHeight |
number | No | auto | Height of data rows in px |
headerHeight |
number | No | auto | Height of the header row in px |
minCellWidth |
number | No | auto | Minimum column width in px |
maxCellWidth |
number | No | auto | Maximum column width in px |
padding |
number | No | auto | Cell padding in px |
backgroundColor |
string | No | "" |
Background fill color |
backgroundCornerRadius |
number | No | 0 |
Corner radius of the background rect |
backgroundOpacity |
number | No | 1 |
Opacity of the background rect |
showBackground |
boolean | No | false |
Whether to render a background rect |
* Either equation or data must be provided.
Example
const table = new omdTable();
table.loadFromJSON({
equation: 'y=3x+2',
xMin: 0,
xMax: 5,
stepSize: 1,
headers: ['x', 'y'],
alternatingRowColors: true
});
display.load(table);
ratioChart
Renders a ratio or fraction visualization in one of several styles.
Example JSON
{ "omdType": "ratioChart", "valueA": 3, "valueB": 5, "renderType": "tile", "size": "medium" }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
valueA |
number | Yes* | — | First value (or use numerator) |
valueB |
number | Yes* | — | Second value (or use denominator) |
numerator |
number | No* | — | Alias for valueA |
denominator |
number | No* | — | Alias for valueB |
renderType |
'pie'|'dots'|'dot'|'tile'|'bar' |
No | 'pie' |
Visual style for the chart |
size |
'small'|'medium'|'large' |
No | 'medium' |
Preset size of the visualization |
* Either valueA/valueB or numerator/denominator must be provided.
Example
const chart = new omdRatioChart();
chart.loadFromJSON({
valueA: 3,
valueB: 5,
renderType: 'tile',
size: 'medium'
});
display.load(chart);
spinner
Renders a circular spinner divided into equal sections with an arrow.
Example JSON
{ "omdType": "spinner", "divisions": 6, "arrowPosition": 90, "size": "large" }
Fields
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
divisions |
number | Yes | — | Number of equal sections on the spinner |
arrowPosition |
number | No | 0 |
Arrow angle in degrees (0 = top) |
size |
'small'|'medium'|'large' |
No | 'medium' |
Preset size of the spinner |
Example
const spinner = new omdSpinner();
spinner.loadFromJSON({
divisions: 6,
arrowPosition: 90,
size: 'large'
});
display.load(spinner);