pgraphJS is an HTML/JavaScript component for displaying an editable 2D curve on X/Y axes.
The name pgraph comes from "parametric graph", as the curve is defined by a set of control points like a paramtric EQ.
It lets you configure curve control points, lock selected points, choose how points are connected, and evaluate a y value from an x value.
- Responsive SVG rendering inside any HTML container.
- Control points configured as plain objects.
- Fixed or editable points.
- Per-axis locking with
lockXandlockY. - Curve types:
linear,step,bezier,smooth. - Built-in grid and axes.
- Optional X/Y labels, min/max values, axis graduations, and configurable grid resolution.
- Optional value snapping with
snap. - JavaScript API with
dragstart,input, andchangeevents. - Pure
evaluatePGraph(config, x)function that works without creating a DOM component. - Browser custom element available as
<p-graph>. - CSS variable based styling, ready for future themes.
npm install
npm run buildThe build generates:
dist/pgraph.js: non-minified build with JSDoc comments.dist/pgraph.min.js: minified build.dist/pgraph.css: base styles.dist/pgraph_*.css: optional themes.
<link rel="stylesheet" href="./dist/pgraph.css">
<div id="graph" style="width: 640px; height: 320px;"></div>
<script src="./dist/pgraph.min.js"></script>
<script>
const graph = createPGraph(document.querySelector('#graph'), {
points: [
{ x: 0, y: 0, fixed: true },
{ x: 50, y: 80 },
{ x: 100, y: 20, fixed: true },
],
curve: 'smooth',
snap: 1,
});
graph.on('change', ({ points }) => {
console.log('Updated points:', points);
});
console.log(graph.evaluate(25));
</script>const { createPGraph, evaluatePGraph } = require('pgraph');
const value = evaluatePGraph({
points: [
{ x: 0, y: 0 },
{ x: 10, y: 20 },
],
}, 5);
console.log(value); // 10<link rel="stylesheet" href="./dist/pgraph.css">
<script src="./dist/pgraph.min.js"></script>
<p-graph
style="display: block; width: 640px; height: 320px;"
config='{
"curve": "linear",
"points": [
{ "x": 0, "y": 0, "fixed": true },
{ "x": 50, "y": 80 },
{ "x": 100, "y": 20, "fixed": true }
]
}'
></p-graph>const config = {
minX: 0,
maxX: 100,
minY: 0,
maxY: 100,
pointCount: null,
curve: 'linear',
padding: 28,
grid: true,
gridResolution: 4,
labelX: '',
labelY: '',
showMinMax: false,
axisGraduation: false,
axisResolution: null,
snap: null,
points: [
{ id: 'start', x: 0, y: 0, fixed: true },
{ id: 'middle', x: 50, y: 70 },
{ id: 'end', x: 100, y: 100, fixed: true },
],
};| Option | Type | Default | Description |
|---|---|---|---|
minX |
number |
inferred or 0 |
Minimum value on the X axis. |
maxX |
number |
inferred or 1 |
Maximum value on the X axis. |
minY |
number |
inferred or 0 |
Minimum value on the Y axis. |
maxY |
number |
inferred or 1 |
Maximum value on the Y axis. |
points |
PGraphPoint[] |
two fixed points | Curve control points. |
pointCount |
number | null |
null |
Minimum number of points. Missing points are inserted between the first and last points. |
curve |
linear | step | bezier | smooth |
linear |
Connection type between points. |
padding |
number |
28 |
Internal SVG padding in pixels. |
grid |
boolean |
true |
Enables or disables the grid. |
gridResolution |
number |
4 |
Number of background grid subdivisions on each axis. |
labelX |
string |
'' |
Label displayed below the X axis. |
labelY |
string |
'' |
Label displayed beside the Y axis. |
showMinMax |
boolean |
false |
Shows the min/max values for X and Y axes. |
axisGraduation |
boolean |
false |
Shows axis tick marks and values. |
axisResolution |
number | null |
null |
Tick spacing in data units when axisGraduation is enabled. Uses an automatic spacing when null. |
snap |
number | null |
null |
Snapping step used while dragging points. |
{
id: 'point-1',
x: 50,
y: 80,
fixed: false,
lockX: false,
lockY: false,
}| Property | Type | Default | Description |
|---|---|---|---|
id |
string |
generated | Optional point identifier. |
x |
number |
required | Position on the X axis. |
y |
number |
required | Position on the Y axis. |
fixed |
boolean |
false |
Fully locks the point. |
lockX |
boolean |
false |
Locks horizontal movement only. |
lockY |
boolean |
false |
Locks vertical movement only. |
Creates a PGraph instance inside an HTML container.
const graph = createPGraph(document.querySelector('#graph'), {
points: [
{ x: 0, y: 0 },
{ x: 1, y: 1 },
],
});Computes a y value from a configuration without creating a graphical component.
const y = evaluatePGraph({
points: [
{ x: 0, y: 0 },
{ x: 10, y: 20 },
],
}, 5);Computes a y value from the current curve.
const y = graph.evaluate(42);Merges a new configuration into the current state and redraws the graph.
graph.setConfig({
curve: 'step',
snap: 5,
});Replaces the control points.
graph.setPoints([
{ x: 0, y: 20, fixed: true },
{ x: 50, y: 90 },
{ x: 100, y: 10, fixed: true },
]);Returns a copy of the current points.
const points = graph.getPoints();Returns the normalized configuration and current points.
const state = graph.getState();Listens to a PGraph event and returns an unsubscribe function.
const off = graph.on('input', ({ point, index, value }) => {
console.log(index, point, value);
});
off();Available events:
dragstart: emitted when the user starts dragging a point.input: emitted while a point is being dragged.change: emitted after a change is committed.
Each event is also dispatched on the container as a DOM CustomEvent with the pgraph: prefix.
document.querySelector('#graph').addEventListener('pgraph:change', (event) => {
console.log(event.detail);
});Destroys the instance, removes global listeners, and removes the generated DOM.
graph.destroy();Base styles expose CSS variables. Load pgraph.css first, then optionally load a theme file.
<link rel="stylesheet" href="./dist/pgraph.css">
<link rel="stylesheet" href="./dist/pgraph_bootstrap5.css">Available theme files:
pgraph_simple.csspgraph_modern.csspgraph_midnight.csspgraph_bootstrap5.csspgraph_bootstrap5_dark.css
Themes apply to .pgraph globally and also expose scoped classes such as .pgraph-theme-modern and .pgraph-theme-bootstrap5. The Bootstrap themes use Bootstrap CSS variables when they exist, with built-in fallback colors otherwise.
.my-graph .pgraph {
--pgraph-background: #ffffff;
--pgraph-border: transparent;
--pgraph-border-radius: 0;
--pgraph-axis: #30363d;
--pgraph-grid: #d8dee6;
--pgraph-curve: #1264d8;
--pgraph-point: #ffffff;
--pgraph-point-border: #1264d8;
--pgraph-point-radius: 6px;
--pgraph-fixed-point: #78828f;
--pgraph-focus: #ffb000;
}Bootstrap, Angular, and vanilla CSS themes can hook into these variables without changing the JavaScript API.
npm run check
npm run build
npm testApache-2.0