# Bar chart
## Microsim
### Live player
<div class="microsim-player">
<iframe src="https://editor.p5js.org/sciencenibber/full/z-LBlAFpt" width="100%" height="620" frameborder="0" sandbox="allow-scripts allow-same-origin"></iframe>
</div>
<div class="microsim-fallback">
<img src="Microsims/thumbs/Bar_chart.png" alt="Bar_chart microsim poster" style="width:100%;border:1px solid #4445;border-radius:6px;">
<p><em>Live microsim (desktop) · <a href="https://editor.p5js.org/sciencenibber/sketches/z-LBlAFpt">open sketch in the p5.js editor</a></em></p>
</div>
**Editor URL:** https://editor.p5js.org/sciencenibber/sketches/z-LBlAFpt
**Description (100 words):**
Eight monthly values rendered as labeled bars over a tick-and-grid chart frame. Hover any bar for a tooltip that follows the cursor and clamps to the canvas edge. The "sort by value" button toggles between calendar order and a descending sort, so the reader can compare the same data through two orderings without losing the encoding. The "non-zero baseline" slider deliberately violates Tufte's most famous rule — lifting the y-axis off zero exaggerates differences and lights a red warning ribbon with a live lie-factor readout. The category-colours toggle swaps the neutral hue for a Tableau-10 palette, demonstrating the data-ink tax that decorative encoding levies.
```js
// =====================================================================
// Bar_chart.js · GENERATIVE / Visualization room (Pattern A composition)
//
// Canonical bar-chart microsim for the Wikitube wiki. Renders a small
// monthly dataset as vertical bars over a labelled chart frame, with a
// hover tooltip, a sort-by-value toggle, and an opt-in non-zero baseline
// slider that lights up a warning ribbon when engaged (the canonical
// Tufte "lie factor" violation, made visible).
//
// This sketch is the reference implementation referenced by P5_JS_EDITOR
// section 11 — every other Pattern A chart in the room (Line_chart,
// Scatter_plot, Histogram, ...) forks from it by swapping the inner
// glyph loop while keeping the chart-frame, scale closures, tooltip, and
// HUD untouched.
//
// Parameters (controls):
// sortBtn — flip between calendar order and value-sorted bars.
// baselineSlider — 0 (zero baseline, honest) ... 100 (zoomed-in
// baseline, dishonest). Triggers a red warning
// ribbon along the top of the chart frame.
// colorBtn — toggle a categorical hue per bar (decorative,
// low-information) versus a single neutral hue
// (high data-ink ratio).
// =====================================================================
// Single source of truth — used by HUD and the en.wikitube.io URL.
const ARTICLE = "Bar_chart";
// Silence the p5.js Friendly Errors System. The web editor adds extra
// runtime cost per draw call when FES is on, and our HUD does not need
// hand-holding for missing-arg warnings.
p5.disableFriendlyErrors = true;
// ---------------------------------------------------------------------
// Visual constants — Visualization-room neutral palette from §11.
// ---------------------------------------------------------------------
const BG = 250; // near-white "ink on paper" canvas
const FG = 24; // body-text grey
const AXIS = [80, 90, 110]; // tick lines and axis titles
const GRIDC = [200, 205, 215]; // horizontal gridlines, very pale
const INK = [40, 48, 60]; // chart title and labels
const BAR = [70, 130, 200]; // default bar fill (blue)
const BAR_HI = [220, 110, 60]; // hovered-bar accent (orange)
const WARN = [220, 60, 60]; // non-zero-baseline warning ribbon
const MUTED = [140, 150, 165]; // disabled / dim text
// Categorical palette used by the colorBtn toggle. Eight hues chosen
// from the Tableau-10 set for maximum perceptual distance.
const CAT8 = [
[ 78, 121, 167], [242, 142, 43], [225, 87, 89], [118, 183, 178],
[ 89, 161, 79], [237, 201, 72], [176, 122, 161], [255, 157, 167],
];
// Outer chart margins — leave room for axis labels, legend, and HUD.
const MARGIN = { top: 64, right: 24, bottom: 88, left: 72 };
// Eight months of demo data. Anyone forking this sketch will replace
// `data` with their own; everything else can stay verbatim.
const data = [
{ label: "Jan", value: 42 }, { label: "Feb", value: 37 },
{ label: "Mar", value: 55 }, { label: "Apr", value: 28 },
{ label: "May", value: 71 }, { label: "Jun", value: 49 },
{ label: "Jul", value: 64 }, { label: "Aug", value: 38 },
];
// Mutable UI state. Read at the top of draw() into named locals so the
// rest of the frame is a pure function of the snapshot.
let sortBtn, baselineSlider, colorBtn;
let sorted = false;
let coloured = false;
function setup() {
createCanvas(windowWidth, windowHeight);
textFont("system-ui");
textAlign(CENTER, CENTER);
// Bottom-left control rail. Three controls stacked vertically; each
// line is one row of (label, control) so the layout reads as a list.
sortBtn = createButton("sort by value")
.position(20, height - 80)
.size(180, 24)
.mousePressed(() => { sorted = !sorted; });
baselineSlider = createSlider(0, 100, 0, 1)
.position(220, height - 76)
.size(200);
colorBtn = createButton("toggle category colours")
.position(20, height - 50)
.size(220, 24)
.mousePressed(() => { coloured = !coloured; });
}
function draw() {
background(BG);
// -------------------------------------------------------------------
// Snapshot all interactive state into pure-function locals.
// -------------------------------------------------------------------
const view = sorted
? [...data].sort((a, b) => b.value - a.value)
: data;
const baselineFraction = baselineSlider.value() / 100; // 0..1
// Chart-frame rectangle in canvas coords.
const x0 = MARGIN.left, y0 = MARGIN.top;
const w = width - MARGIN.left - MARGIN.right;
const h = height - MARGIN.top - MARGIN.bottom;
// Y-axis range. yMax is rounded up to the next ten; yMin lifts off
// zero in proportion to baselineFraction (so the slider literally
// visualises the lie factor).
const rawMax = Math.max(...view.map(d => d.value));
const yMax = Math.ceil(rawMax / 10) * 10;
const yMin = baselineFraction * (yMax - 10);
// Scale closures. xScale maps a bar index to the centre of its slot;
// yScale maps a value (in [yMin, yMax]) to a canvas y-coord (top is
// small in pixel space, big in value space, hence the inversion).
const xScale = (i) => x0 + (i + 0.5) * (w / view.length);
const yScale = (v) => y0 + h - ((v - yMin) / (yMax - yMin)) * h;
// Draw the frame (gridlines, axes, ticks, titles) before the bars
// so the bars sit on top of the gridlines, not beneath them.
drawChartFrame(x0, y0, w, h, view, yMin, yMax);
// Hit-test once per frame — find the bar (if any) under the cursor.
// Reading mouseX/mouseY directly is simpler and faster than wiring
// mouseEntered/Exited handlers per bar.
const barW = (w / view.length) * 0.7;
let hovered = -1;
for (let i = 0; i < view.length; i++) {
const cx = xScale(i);
const top = yScale(view[i].value);
if (mouseX > cx - barW / 2 && mouseX < cx + barW / 2 &&
mouseY > top && mouseY < y0 + h) {
hovered = i;
}
}
// Emit the bars. Each bar is one rect from baseline to value. Colour
// depends on the colour toggle and on hover state.
for (let i = 0; i < view.length; i++) {
const cx = xScale(i);
const top = yScale(view[i].value);
const base = y0 + h;
const col = (i === hovered)
? BAR_HI
: (coloured ? CAT8[i % CAT8.length] : BAR);
fill(...col); noStroke();
rect(cx - barW / 2, top, barW, base - top, 2);
// Category label under the bar.
fill(...AXIS); textSize(11); textAlign(CENTER, TOP);
text(view[i].label, cx, base + 6);
}
// Tooltip — clamped so it never escapes the canvas right edge.
if (hovered >= 0) drawTooltip(mouseX, mouseY, view[hovered]);
// Warning ribbon when the baseline slider is off zero.
if (baselineFraction > 0.001) drawLieRibbon(x0, y0, w);
drawHud();
drawControlHints();
drawReadout(view, hovered, yMin, yMax);
drawEquation();
}
// =====================================================================
// Chart-frame helper. Will eventually move to chart_frame.js but lives
// inline here so the reference sketch stands alone.
// =====================================================================
function drawChartFrame(x, y, w, h, view, yMin, yMax) {
// Horizontal gridlines (six of them, including the top and bottom).
stroke(...GRIDC); strokeWeight(1);
for (let t = 0; t <= 5; t++) {
const yy = y + h - (t / 5) * h;
line(x, yy, x + w, yy);
}
// Y and X axis lines.
stroke(...AXIS); strokeWeight(1.5);
line(x, y, x, y + h);
line(x, y + h, x + w, y + h);
// Y-tick labels — six values across [yMin, yMax].
noStroke(); fill(...AXIS); textAlign(RIGHT, CENTER); textSize(10);
for (let t = 0; t <= 5; t++) {
const yy = y + h - (t / 5) * h;
const v = yMin + (t / 5) * (yMax - yMin);
text(nf(v, 1, 0), x - 6, yy);
}
// Y-axis title — rotated 90 degrees CCW so it reads bottom-to-top.
push(); translate(x - 50, y + h / 2); rotate(-HALF_PI);
fill(...AXIS); textAlign(CENTER, CENTER); textSize(12);
text("value", 0, 0); pop();
// X-axis title.
fill(...AXIS); textAlign(CENTER, TOP); textSize(12);
text("month", x + w / 2, y + h + 26);
// Chart title — left-aligned, just above the frame.
fill(...INK); textAlign(LEFT, TOP); textSize(14);
text("Monthly value - " + (sorted ? "sorted by value" : "calendar order"),
x, y - 22);
textAlign(CENTER, CENTER);
}
// Tooltip: a dark pill that follows the cursor. Width is computed from
// the text so it never trims the value.
function drawTooltip(mx, my, d) {
const tip = `${d.label}: ${d.value}`;
textSize(12); textAlign(LEFT, TOP);
const tw = textWidth(tip) + 16;
const tx = constrain(mx + 12, 0, width - tw - 4);
const ty = constrain(my + 12, 0, height - 28);
noStroke(); fill(0, 200);
rect(tx, ty, tw, 22, 4);
fill(255); text(tip, tx + 8, ty + 5);
textAlign(CENTER, CENTER);
}
// Red ribbon along the top of the chart frame, with the lie factor
// printed in the corner. Lights up only when baselineFraction > 0.
function drawLieRibbon(x, y, w) {
noStroke(); fill(...WARN, 60);
rect(x, y - 6, w, 4);
fill(...WARN); textSize(11); textAlign(LEFT, BOTTOM);
const lie = 1 / (1 - (baselineSlider.value() / 100) * 0.999);
text("non-zero baseline - lie factor " + nf(lie, 1, 2) + "x",
x, y - 8);
textAlign(CENTER, CENTER);
}
// =====================================================================
// HUD overlay — title TL, Wikitube URL TL, control hints TR,
// readouts BL, equation BR. Per Visualization §11 + Betterfire Standard.
// =====================================================================
function drawHud() {
// Top-left strap with article title and the canonical Wikitube URL.
noStroke(); fill(0, 180); rect(8, 8, 380, 26);
fill(255); textSize(13); textAlign(LEFT, TOP);
text(ARTICLE + " - en.wikitube.io/wiki/" + ARTICLE, 16, 14);
textAlign(CENTER, CENTER);
}
function drawControlHints() {
// Top-right: which controls do what.
textAlign(RIGHT, TOP); textSize(11); noStroke(); fill(...MUTED);
text("hover bars for tooltip", width - 14, 14);
text("button: sort by value", width - 14, 30);
text("slider: non-zero baseline", width - 14, 46);
text("button: category colours", width - 14, 62);
textAlign(CENTER, CENTER);
}
function drawReadout(view, hovered, yMin, yMax) {
// Bottom-left: live snapshot of pertinent numbers.
textAlign(LEFT, BOTTOM); textSize(11); noStroke(); fill(...MUTED);
const total = view.reduce((s, d) => s + d.value, 0);
const mean = total / view.length;
let line1 = "n " + view.length + " sum " + total + " mean " + nf(mean, 1, 1);
let line2 = "y in [" + nf(yMin, 1, 1) + ", " + yMax + "]";
if (hovered >= 0) {
line2 += " - hover " + view[hovered].label + " " + view[hovered].value;
}
text(line1, 20, height - 14);
text(line2, 20, height - 28);
textAlign(CENTER, CENTER);
}
function drawEquation() {
// Bottom-right: the rendering equation, exactly as in P5_JS_EDITOR §11.
textAlign(RIGHT, BOTTOM); textSize(11); noStroke(); fill(...MUTED);
text("y_pixel = y0 + h - (v - yMin) / (yMax - yMin) * h",
width - 14, height - 14);
textAlign(CENTER, CENTER);
}
// Resize the canvas with the window. Controls keep their absolute
// positions because they were created with createButton/createSlider —
// but we re-anchor the bottom row so it follows the new height.
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
sortBtn.position(20, height - 80);
baselineSlider.position(220, height - 76);
colorBtn.position(20, height - 50);
}
```
## Links (Wikipedia order)
<!-- injected from _registry/childlinks/Bar_chart.json (2026-07-30T02:09:12Z) -->
`3D_computer_graphics` · `Accelerated_failure_time_model` · `Actuarial_science` · `Akaike_information_criterion` · `Analysis_of_covariance` · `Analysis_of_variance` · `Anderson–Darling_test` · `Anscombe_transform` · `Arithmetic_mean` · `Arithmetic–geometric_mean` · `Asymptotic_theory_(statistics)` · [[Autocorrelation]] · `Autoregressive_conditional_heteroskedasticity` · `Autoregressive_model` · `Average_absolute_deviation` · `Bayes_estimator` · `Bayes_factor` · `Bayesian_inference` · `Bayesian_information_criterion` · `Bayesian_linear_regression` · `Bayesian_probability` · `Bias_of_an_estimator` · `Binomial_regression` · [[Bioinformatics]] · `Biostatistics` · `Biplot` · `Blocking_(statistics)` · `Bootstrapping_(statistics)` · [[Box_plot]] · `Box–Jenkins_method` · `Breusch–Godfrey_test` · `Canonical_correlation` · `Cartography` · `Categorical_variable` · `Census` · `Central_limit_theorem` · `Chemometrics` · `Chi-squared_test` · `Clinical_study_design` · `Clinical_trial` · `Cluster_analysis` · `Cluster_sampling` · `Cochran–Mantel–Haenszel_statistics` · `Coefficient_of_determination` · `Coefficient_of_variation` · `Cohen's_kappa` · `Cohort_study` · `Cointegration` · `Completeness_(statistics)` · `Confidence_interval` · `Confounding` · `Contingency_table` · `Contraharmonic_mean` · `Control_chart` · `Correlogram` · `Count_data` · `Credible_interval` · `Crime_statistics` · `Cross-correlation` · `Cross-sectional_study` · `Cross-validation_(statistics)` · `Cubic_mean` · `Data_and_information_visualization` · `Data_collection` · `Data_preprocessing` · `Data_transformation_(statistics)` · `Decomposition_of_time_series` · `Degrees_of_freedom_(statistics)` · `Demographic_statistics` · `Density_estimation` · `Descriptive_statistics` · `Design_of_experiments` · `Dickey–Fuller_test` · `Dimensionality_reduction` · `Divergence_(statistics)` · `Durbin–Watson_statistic` · `Econometrics` · `Effect_size` · `Efficiency_(statistics)` · `Elliptical_distribution` · `Empirical_distribution_function` · `Engineering_statistics` · `Environmental_statistics` · `Epidemiology` · `Errors_and_residuals` · `Estimating_equations` · `Experiment` · `Exponential_family` · `Exponential_smoothing` · `F-test` · `Factor_analysis` · `Factorial_experiment` · `Failure_rate` · `Fan_chart_(statistics)` · `Feature_scaling` · `First-hitting-time_model` · `Fisher_transformation` · `Forest_plot` · [[Fourier_analysis]] · [[Frequency_domain]] · `Frequentist_inference` · `Friedman_test` · `G-test` · `General_linear_model` · `Generalized_linear_model` · `Generalized_mean` · `Geographic_information_system` · `Geometric_mean` · `Geostatistics` · `Goodness_of_fit` · `Granger_causality` · `Graphical_model` · `Grouped_data` · `Harmonic_mean` · `Height` · `Heinz_mean` · `Heronian_mean` · [[Histogram]] · `Hodges–Lehmann_estimator` · `Homoscedasticity_and_heteroscedasticity` · `Index_of_dispersion` · `Interaction_(statistics)` · `Interquartile_range` · `Interval_estimation` · `Isotonic_regression` · `Jackknife_resampling` · `James_R._Beniger` · `Jarque–Bera_test` · `Johansen_test` · `Jonckheere's_trend_test` · `Jurimetrics` · `Kaplan–Meier_estimator` · `Kendall_rank_correlation_coefficient` · `Kolmogorov–Smirnov_test` · `Kriging` · `Kruskal–Wallis_test` · `Kurtosis` · `L-moment` · `LM3914` · [[Least-squares_spectral_analysis]] · `Lehmann–Scheffé_theorem` · `Lehmer_mean` · `Length` · `Likelihood-ratio_test` · `Likelihood_function` · `Lilliefors_test` · [[Line_chart]] · `Linear_discriminant_analysis` · `Linear_regression` · `List_of_fields_of_application_of_statistics` · `List_of_statistical_tests` · `List_of_statistics_articles` · `Ljung–Box_test` · `Location_parameter` · `Location–scale_family` · `Logistic_regression` · `Loss_function` · `Lp_space` · `M-estimator` · `Mann–Whitney_U_test` · `Marshall_Clagett` · `Maximum_a_posteriori_estimation` · `McNemar's_test` · `Median` · `Medical_statistics` · `Method_of_moments_(statistics)` · `Methods_engineering` · `Minimum-variance_unbiased_estimator` · `Misleading_graph` · `Missing_data` · `Mixed_model` · `Mode_(statistics)` · `Model_selection` · `Moment_(mathematics)` · `Monotone_likelihood_ratio` · `Multivariate_analysis_of_variance` · `Multivariate_normal_distribution` · `Multivariate_statistics` · `National_accounts` · `Natural_experiment` · `Nelson–Aalen_estimator` · `Nicole_Oresme` · `Nonlinear_regression` · `Nonparametric_regression` · `Nonparametric_statistics` · `Normalization_(statistics)` · `Observational_study` · `Official_statistics` · `One-_and_two-tailed_tests` · `Opinion_poll` · `Optimal_decision` · `Order_statistic` · `Ordinary_least_squares` · `Outlier` · `Outline_of_statistics` · `Parametric_statistics` · `Partial_autocorrelation_function` · `Partial_correlation` · `Partition_of_sums_of_squares` · `Pearson_correlation_coefficient` · `Percentile` · `Permutation_test` · `Pie_chart` · `Pivotal_quantity` · `Point_estimation` · `Poisson_regression` · `Posterior_probability` · `Power_(statistics)` · `Power_transform` · `Prediction_interval` · `Principal_component_analysis` · `Prior_probability` · `Probabilistic_design` · `Probability_distribution` · `Product_(mathematics)` · `Progress_bar` · `Proportional_hazards_model` · `Psychometrics` · `Quality_control` · `Quasi-experiment` · `Questionnaire` · `Q–Q_plot` · `Radar_chart` · `Random_assignment` · `Randomized_controlled_trial` · `Randomized_experiment` · `Range_(statistics)` · `Rank_correlation` · `Ranking_(statistics)` · `Rao–Blackwell_theorem` · `Regression_analysis` · `Regression_validation` · [[Reliability_engineering]] · `Replication_(statistics)` · `Resampling_(statistics)` · `Robust_regression` · `Robust_statistics` · `Run_chart` · `Sample_size_determination` · `Sampling_(statistics)` · `Sampling_distribution` · `Scale_parameter` · [[Scatter_plot]] · `Scientific_control` · `Score_test` · `Seasonal_adjustment` · `Semiparametric_regression` · `Shape_parameter` · `Shapiro–Wilk_test` · `Sign_test` · `Simple_linear_regression` · `Simultaneous_equations_model` · `Skewness` · `Social_statistics` · `Spatial_analysis` · `Spearman's_rank_correlation_coefficient` · `Spectral_density_estimation` · `Standard_deviation` · `Standard_error` · `Standard_score` · `Stationary_process` · `Statistic` · `Statistical_classification` · `Statistical_dispersion` · `Statistical_distance` · `Statistical_graphics` · `Statistical_hypothesis_test` · `Statistical_inference` · `Statistical_model` · `Statistical_parameter` · `Statistical_population` · `Statistical_process_control` · `Statistical_theory` · `Statistics` · `Stem-and-leaf_display` · `Stochastic_approximation` · `Stratified_sampling` · `Structural_break` · `Structural_equation_modeling` · `Student's_t-test` · `Sufficient_statistic` · `Survey_methodology` · `Survival_analysis` · `Survival_function` · [[System_identification]] · [[Time_domain]] · [[Time_series]] · `Titanic` · `Tolerance_interval` · `Truncation_(statistics)` · `U-statistic` · `Uniformly_most_powerful_test` · `V-statistic` · `Van_der_Waerden_test` · `Variance` · `Variance-stabilizing_transformation` · `Vector_autoregression` · `Violin_plot` · `Wald_test` · `Wavelet` · `Whittle_likelihood` · `Wilcoxon_signed-rank_test` · `William_Playfair` · `Winsorizing` · `Z-test`
## From the Real GENERATIVE library

*Bar chart — placed from the Real G.E.N.E.R.A.T.I.V.E. course library (Visualization room). Source: Wikimedia Commons (via Wikipedia article media). [Details & license](https://commons.wikimedia.org/wiki/File:Human_losses_of_world_war_two_by_country.png).*
> A bar chart or bar graph is a chart or graph that presents categorical data with rectangular bars with heights or lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. ([Wikipedia](https://en.wikipedia.org/wiki/Bar_chart))
<!-- REAL-GENERATIVE-MEDIA:END -->
<!-- LOCAL-MEDIA-PASS:START -->
## From the vault media library
!Bar chart thumb.png
*Bar Chart — from the vault's own media holdings, placed 2026-07-09. MTN / Wikitube.io original · CC BY-SA 4.0.*
<!-- LOCAL-MEDIA-PASS:END -->
> **Room:** Visualization · **Status:** ✅ shipped
## Overview
A **bar chart** is the canonical statistical graphic for comparing a quantitative value across a set of categories. Each category is given an equal slice of one axis and a rectangle whose length on the perpendicular axis is proportional to its value, so the eye reads "tallest = largest" with no further translation. The form was popularised by William Playfair in the *Commercial and Political Atlas* (1786) and remains, two and a half centuries later, the default chart taught in every introductory statistics course.
The visual contract is unforgiving. Bars must share a common baseline of zero, otherwise differences in length stop encoding differences in value and the chart becomes a Tufte-grade lie factor. Spacing is uniform, the order of the bars is part of the message (calendar, alphabetical, sorted by value), and any color encoding should add [[Information|information]] rather than ornament — if every bar is a different color for no reason, the reader's preattentive [[System|system]] pays a tax for nothing.
This microsim ships the room's reference [[Implementation|implementation]]: a `drawChartFrame` axis system, a `glyphBar` primitive, hover-driven tooltips, a sort-by-value toggle, and an opt-in non-zero-baseline slider that lights up a warning ribbon — the canonical Tufte violation, made visible.
## See also
- Room hub: Visualization
- p5.js Editor conventions: P5 JS EDITOR
- Wiki root: MAIN
---
*Scaffolded by `generative-microsim` from row 0 of the Visualization sheet on 2026-04-30T12:51:52Z.*
<!-- REAL-GENERATIVE-MEDIA:START -->
<!-- CRAFT-LINK:START g12 -->
*Built to the [[WT!P5_js_Microsim_Master_Class|p5.js Master Class]].*
<!-- CRAFT-LINK:END -->
## Wikipedia : Wikitube
**Strict pair:** [Wikipedia](https://en.wikipedia.org/wiki/Bar_chart) : [Wikitube](https://en.wikitube.io/wiki/Bar_chart)
## Previous hub tags
Tree parents: [[Monte_Carlo_method]] · [[Reliability_engineering]].
Legacy hubs: `GENERATIVE`.
---
*Sources: 1 legacy note. Minted wave 1, 2026-07-30 (v1.6 order).*