TaperedProcessDiagram is a lightweight D3-based library for building these visuals on the web: animated, responsive, and fully configurable. Use cases: clinical trial pipelines, machine learning model pipelines, data ingestion workflows, regulatory submission processes — any multi-stage system that narrows from raw input to refined output is a natural fit for a tapered process diagram.
Quick start
GitHub: https://github.com/prosvitco/D3TaperedProcessDiagram
Drop it into any web page — a clinical data platform, a research dashboard, a scientific publication site. The only dependency is D3 v7, loaded from CDN. No build step, no bundler required.
<!-- 1. Load D3 -->
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
<!-- 2. Load the library -->
<script src="tapered-process-diagram.js"></script>
<!-- 3. Place an SVG target -->
<svg id="chart-1"></svg>
<!-- 4. Initialise -->
<script>
initTaperedProcessDiagram({
el: "#chart-1",
data: chartData,
options: { direction: "ltr" },
animate: true
});
</script>
Library API
tapered-process-diagram.js exposes four globals. The host page owns the dataset and initialization flow — making it easy to drive from a CMS, a REST API, or a static JSON file.
| Export | Description |
|---|---|
TaperedProcessDiagram | Class. Instantiate directly for fine-grained control. |
initTaperedProcessDiagram({ el, data, options, animate }) | Convenience wrapper. Creates an instance, calls render(), and returns it. |
initAllTaperedProcessDiagrams(configs) | Maps an array of configs through initTaperedProcessDiagram. |
restartAllTaperedProcessDiagrams(diagrams) | Calls restartAnimation() on each instance. |
Restart animation
Useful for presentations, demos, or interactive reports where you want the animation to replay on demand.
const diagram = initTaperedProcessDiagram({ el: "#chart-1", data, animate: true });
diagram.restartAnimation();
Or restart multiple diagrams at once — handy when a page shows several pipeline variants side by side:
const diagrams = initAllTaperedProcessDiagrams(chartConfigs);
restartAllTaperedProcessDiagrams(diagrams);
Direction demos
The funnel can flow in any of four directions — useful when fitting the diagram into different page layouts. A left-to-right orientation suits wide editorial layouts and process documentation; top-to-bottom works well in narrow columns or mobile-first dashboards; bottom-to-top is a natural fit for visualising data that flows upward toward a conclusion, such as a funnel from raw specimens to a diagnosis. The side: "left" and side: "right" annotation values are canonical — they map correctly regardless of the active direction.
Left → Right "ltr" (default)
Right → Left "rtl"
Top → Bottom "ttb"
Bottom → Top "btt"
Data shape
Each section maps to one stage in your workflow — a phase in a clinical trial, a step in an ETL pipeline, a layer in a data science model. Annotations live directly on the section they describe, so the data structure mirrors the diagram structure. No separate annotation array, no key lookups.
{
startLabel: { label: "Raw Clinical Trial Data", offset: 35 },
endLabel: { label: "Informed Decisions", offset: 35 },
sections: [
{
background: "#c6dbe6",
border: { color: "#4d88a8", width: 1 },
divider: { color: "#179bd7", width: 2 },
width: 0.25,
annotation: {
label: "Data Collection",
side: "left",
color: "#4d88a8"
}
},
// … more sections
]
}
Section fields
| Field | Type | Description |
|---|---|---|
background | string | Fill color of the polygon. |
border.color | string | Polygon outline color. Also used for outer cap borders. |
border.width | number | Polygon outline width. |
divider.color | string | Divider line color at the section boundary. Falls back to border.color. |
divider.width | number | Divider line width. |
width | number | Relative width weight. Sections are normalised — values don’t need to sum to 1. |
annotation | object? | Optional. Omit to render the section without an annotation. |
Annotation fields
| Field | Values | Description |
|---|---|---|
label | string | Annotation text. Use \n for multi-line. |
side | "left" | "right" | Canonical-space side relative to the flow axis. Maps correctly for all four directions. |
color | string | Text and line color. Applied as an inline style — overrides CSS. |
Options reference
Direction
| Value | Flow |
|---|---|
"ltr" | Left → Right (default) |
"rtl" | Right → Left |
"ttb" | Top → Bottom |
"btt" | Bottom → Top |
Layout
| Option | Default | Description |
|---|---|---|
width | 900 | SVG canvas width (viewBox units). |
height | 700 | SVG canvas height (viewBox units). |
funnelLeftX | 220 | Canonical start of the tapered body. |
funnelRightX | 650 | Canonical end of the tapered body. |
leftHalf | 140 | Half-height at the wide cap. |
rightHalf | 45 | Half-height at the narrow cap. |
Annotation spacing
| Option | Default | Description |
|---|---|---|
annotationTextOffset | 70 | Distance from funnel edge to text block. |
annotationLineGap | 18 | Gap between text block and line start. |
annotationLineTargetGap | 12 | Gap between line end and arrowhead tip. |
annotationLineHeight | 24 | Line height for multi-line annotation text. |
Animation
| Option | Default | Description |
|---|---|---|
stageDuration | 700 | Duration of each section’s enter transition (ms). |
stageDelay | 350 | Stagger delay between sections (ms). |
fadeDuration | 420 | Duration of annotation fade-in (ms). |
Outer border behaviour
The two cap borders are derived from the first and last section’s border values. Top and bottom edge lines are intentionally omitted — the tapered polygon edges act as the visual boundary.
- Wide-end border →
sections[0].border - Narrow-end border →
sections[sections.length - 1].border
Responsive behaviour
The SVG uses a fixed viewBox and scales fluidly via CSS — no resize listeners, no JavaScript layout calculations. It works out of the box in responsive WordPress themes, React apps, and static site generators alike.
svg {
width: 100%;
height: auto;
display: block;
}
Pass multiple configs to initAllTaperedProcessDiagrams to render several pipeline variants side by side — useful when comparing trial phases, model architectures, or data processing strategies on a single page.