Histogram Charts
A histogram visualizes the distribution of a dataset by grouping values into contiguous bins and displaying each bin as a bar whose height represents the count (or frequency) within that range. Typical use cases include frequency distributions, population statistics, and scientific data analysis.
SciChart.js has no dedicated histogram series type. Histograms are assembled from FastRectangleRenderableSeriesš with XyxyDataSeriesš, using EColumnMode.StartEndš to place each bar between explicit bin boundaries on the X axis.
The JavaScript Histogram Chart Example can be found in the SciChart.JS Examples Suite on GitHub, or in the live demo at scichart.com/demo.
Create a Histogramā
// Histogram bins: each entry defines [x, x1, y] = [binStart, binEnd, count]
// representing Europe's population by age bracket (simplified)
const bins = [
{ x: 0, x1: 20, y: 150_000_000 },
{ x: 20, x1: 30, y: 75_000_000 },
{ x: 30, x1: 45, y: 112_000_000 },
{ x: 45, x1: 65, y: 138_000_000 },
{ x: 65, x1: 70, y: 32_000_000 },
{ x: 70, x1: 80, y: 48_000_000 },
];
const histogramSeries = new FastRectangleRenderableSeries(wasmContext, {
dataSeries: new XyxyDataSeries(wasmContext, {
xValues: bins.map(b => b.x),
yValues: bins.map(b => b.y),
x1Values: bins.map(b => b.x1),
y1Values: bins.map(() => 0),
}),
columnXMode: EColumnMode.StartEnd,
columnYMode: EColumnYMode.TopBottom,
fillLinearGradient: new GradientParams(new Point(0, 0), new Point(0, 1), [
{ color: "rgba(70, 130, 180, 0.9)", offset: 0 },
{ color: "rgba(70, 130, 180, 0.3)", offset: 1 },
]),
strokeThickness: 0,
topCornerRadius: 4,
opacity: 0.85,
dataLabels: {
style: { fontSize: 13, fontFamily: "Arial" },
color: "white",
}
});
In the code above:
- Each bin is defined as
{ x, x1, y }ā bin start, bin end, and count. XyxyDataSeriesstoresxValues(bin starts),x1Values(bin ends),yValues(bar tops ā the counts), andy1Values(bar bottoms ā all zero, the baseline).columnXMode: EColumnMode.StartEndtells the series thatxandx1are explicit start/end positions on the X axis ā each bar fills exactly its bin range with no gaps.columnYMode: EColumnYMode.TopBottomtells the series thatyis the bar top andy1is the bottom.fillLinearGradientapplies a vertical blue gradient from the bar top to bottom.topCornerRadius: 4rounds the top corners;strokeThickness: 0removes the border.dataLabelsrenders the count above each bar using the default Y value formatter.
Data Aggregationā
The demo above uses pre-aggregated data. In practice, you start from raw measurements and bin them using breakpoints:
function aggregateToBins(
values: number[],
breakpoints: number[]
): { xValues: number[]; x1Values: number[]; yValues: number[] } {
const xValues: number[] = [];
const x1Values: number[] = [];
const yValues: number[] = [];
for (let i = 0; i < breakpoints.length - 1; i++) {
const lo = breakpoints[i];
const hi = breakpoints[i + 1];
xValues.push(lo);
x1Values.push(hi);
yValues.push(values.filter(v => v >= lo && v < hi).length);
}
return { xValues, x1Values, yValues };
}
// Example: bin 1000 random ages into ranges
const rawAges = Array.from({ length: 1000 }, () => Math.random() * 80);
const { xValues, x1Values, yValues } = aggregateToBins(rawAges, [0, 20, 30, 45, 65, 80]);
Pass the result directly into XyxyDataSeries:
new XyxyDataSeries(wasmContext, { xValues, yValues, x1Values })
Axesā
X Axisā
A standard NumericAxisš with axisTitle and a small growBy padding so the outermost bars don't clip against the chart edge:
sciChartSurface.xAxes.add(new NumericAxis(wasmContext, {
axisTitle: "Age (years)",
growBy: new NumberRange(0.05, 0.05)
}));
Y Axisā
Use labelFormat: ENumericFormat.Engineering to display large population counts compactly (e.g. 150M instead of 150000000):
sciChartSurface.yAxes.add(new NumericAxis(wasmContext, {
axisTitle: "Population",
labelFormat: ENumericFormat.Engineering,
growBy: new NumberRange(0, 0.2) // headroom above the tallest bar for data labels
}));
Stylingā
Key styling properties on FastRectangleRenderableSeriesš:
| Property | Purpose |
|---|---|
fillLinearGradient | Vertical gradient fill using GradientParamsš |
fill | Solid fill color (alternative to gradient) |
opacity | Bar transparency (0ā1) |
topCornerRadius | Rounds top corners of each bar |
strokeThickness | Set to 0 to remove bar outlines |
Data Labelsā
dataLabels on the series renders the Y value above each bar. Override dataLabelProvider.getText to format the displayed value:
dataLabels: {
style: { fontSize: 13, fontFamily: "Arial" },
color: "white",
}
To show custom formatted text, override the label provider after construction:
histogramSeries.dataLabelProvider.getText = (state) =>
(state.yVal() / 1_000_000).toFixed(0) + "M";
Chart Modifiersā
Standard zoom and pan modifiers work unchanged with histogram series:
sciChartSurface.chartModifiers.add(
new ZoomPanModifier(),
new ZoomExtentsModifier(),
new MouseWheelZoomModifier()
);
Custom Texture Fillsā
FastRectangleRenderableSeriesš supports a customTextureOptions property that accepts an ICustomTextureOptionsš implementation. This enables pictograph-style (isotype) histograms where bars are filled with a repeating icon pattern ā as seen in the live showcase above, which uses a custom StickFigureTextureOptions class to render proportionally-scaled stick figures inside each bar. For an introduction to custom texture fills see the Custom Texture styling example.