A statistical chart SVG generation library for MoonBit. Supports bar charts, line charts, scatter plots with error bars and multi-series rendering.
Dependencies
moon add JunJunTnT/moonchartimport "JunJunTnT/moonchart"| Library | Mean Render Time | Speedup (vs matplotlib) |
|---|---|---|
| MoonChart | 98.3 μs | 501× |
| ECharts | 1.97 ms | 25× |
| matplotlib | 49.2 ms | 1× |
fn main {
let data = [
DataPoint::withErrY(0.0, 45.0, 3.0),
DataPoint::withErrY(1.0, 62.0, 2.5),
]
let result = Chart::new()
.title("Cell Viability")
.xTicks([0.0, 1.0], ["Control", "Treated"])
.xLabel("Condition")
.yLabel("Viability (%)")
.yRange(0.0, 100.0)
.series(Series::bar("24h", data))
.toSvg()
match result {
Ok(svg) => println(svg)
Err(e) => println("Error: \{e}")
}
}let data = [
DataPoint::withErrY(0.0, 45.0, 3.0),
DataPoint::withErrY(1.0, 62.0, 2.5),
]
Series::bar("Group A", data)
.withColor(Color::rgb(0, 122, 184))
.withBarStroke(Color::rgb(0, 80, 140), 1.0)let data = [
DataPoint::new(0.0, 100.0),
DataPoint::new(1.0, 85.0),
DataPoint::new(2.0, 72.0),
]
Series::line("Trend", data)
.withColor(Color::rgb(212, 57, 57))
.withPointSize(5.0)
.withPointShape(Diamond)
.withLineStyle(Dashed)let data = [
DataPoint::new(1.2, 2.1),
DataPoint::new(2.3, 3.8),
DataPoint::new(3.1, 5.2),
]
Series::scatter("Group X", data)
.withColor(Color::rgb(0, 122, 184))
.withPointSize(5.0)
.withPointShape(Circle)
.withPointFill(Color::rgb(255, 0, 0))let groups = [
BoxGroup::new(0.0, "Control", [1.2, 2.1, 3.4, 2.8, 1.9, 2.5, 3.0, 2.3]),
BoxGroup::new(1.0, "Treated", [0.8, 1.5, 2.9, 2.1, 1.3, 1.9, 2.4, 1.7]),
]
Series::boxplot("Expression", groups)
.withColor(Color::rgb(0, 122, 184))
.withShowOutliers(true)Chart::new()
.series(Series::bar("Experiment", barData))
.series(Series::line("Trend", trendData).withLineStyle(Dashed))| Feature | Bar | Line | Scatter | BoxPlot |
|---|---|---|---|---|
| Error Bars (Y) | ✓ | ✓ | ✓ | — |
| Point Shapes (5 types) | — | ✓ | ✓ | — |
| Line Styles (4 types) | — | ✓ | — | — |
| Custom Color | ✓ | ✓ | ✓ | ✓ |
| Point Fill Color | — | ✓ | ✓ | — |
| Point Size | — | ✓ | ✓ | — |
| Bar Stroke | ✓ | — | — | — |
| Outlier Display | — | — | — | ✓ |
| Dodged Groups | ✓ | — | — | ✓ |
| Method | Default | Description |
|---|---|---|
| Chart::new() | Create a new chart (chart type is per-series) | |
| .title(text) | none | Chart title (centered at top) |
| .size(w, h) | 600 x 400 | Canvas dimensions in pixels |
| .width(w) | 600 | Canvas width only |
| .height(h) | 400 | Canvas height only |
| .xLabel(text) | none | X-axis label |
| .yLabel(text) | none | Y-axis label |
| .xTicks(positions, labels) | auto | X-axis tick positions and display labels |
| .yRange(min, max) | 0, 100 | Y-axis data range |
| .tickFontSize(size) | 11 | Tick label font size (both axes) |
| .labelFontSize(size) | 13 | Axis title font size (both axes) |
| .yGrid(show) | false | Y-axis grid lines |
| .xGrid(show) | false | X-axis grid lines |
| .barWidthRatio(ratio) | 0.7 | Bar/box width as fraction of band width (0.0-1.0) |
| .barGap(gap) | 0.0 | Gap between bars in a group, as fraction of bar width |
| .legend(show, position) | auto | Legend visibility and position |
| .legendFontSize(size) | 12 | Legend font size |
| .margin(top, right, bottom, left) | 40,20,40,50 | Margins around the plot area |
| .background(color) | white | Chart background color |
| .fontFamily(family) | sans-serif | Font family for all text elements |
| .series(s) | Add a single data series | |
| .addSeries(ss) | Add multiple series at once | |
| .toSvg() | Render chart to an SVG string (Result[String, String]) | |
| .save(filename) | Render and write SVG to file (Result[Unit, String]) | |
| .toOption() | Export the internal ChartOption (escape hatch) |
| Constructor | Description |
|---|---|
| Series::bar(name, data) | Bar chart series |
| Series::line(name, data) | Line chart series |
| Series::scatter(name, data) | Scatter plot series |
| Series::boxplot(name, groups) | Box plot series |
| Method | Default | Applies To | Description |
|---|---|---|---|
| .withColor(color) | palette | all | Override series color |
| .withLineWidth(w) | 2.0 | line | Line stroke width |
| .withPointSize(s) | 4.0 | line, scatter | Data point marker radius |
| .withPointShape(shape) | Circle | line, scatter | Marker shape |
| .withLineStyle(style) | Solid | line | Line dash pattern |
| .withPointFill(color) | series color | line, scatter | Point fill color |
| .withBarStroke(color, w) | none | bar | Bar border color and width |
| .withErrorColor(color) | black | all with data | Error bar color (pass None to inherit series color) |
| .withErrorLineWidth(w) | 1.0 | all with data | Error bar line width |
| .withErrorCapWidth(w) | 6.0 | all with data | Error bar cap width |
| .withShowOutliers(show) | true | boxplot | Toggle outlier point display |
DataPoint::new(x, y) // Simple (x, y) point
DataPoint::withErrY(x, y, err) // Symmetric error bar: y ± err
DataPoint::withAsymErrY(x, y, lo, hi) // Asymmetric error bar: +hi, -lo
BoxGroup::new(x, label, values) // Raw data for box plotColor::rgb(r, g, b) // Opaque color (alpha = 255)
Color::rgba(r, g, b, a) // Color with alpha (0-255)AxisOption::defaultX() // Default X axis (auto-infer ticks from data)
AxisOption::linearY() // Default linear Y axis [0, 100]render(opt : ChartOption) -> Result[String, String] // Render a ChartOption to SVG
saveSvg(filename : String, svg : String) -> Result[Unit, String] // Write SVG string to file# Run individual examples
moon run examples/bar_chart # Grouped bar chart with error bars → bar_chart.svg
moon run examples/line_chart # Multi-series line chart → line_chart.svg
moon run examples/scatter_chart # Scatter plot → scatter_chart.svg
moon run examples/boxplot_chart # Box plot → boxplot_chart.svg
moon run examples/mixed_chart # Bar + line mixed chart → mixed_chart.svgTip: All examples use Chart::new()...save("output.svg") to write directly to disk. For programmatic use, replace .save(...) with .toSvg() to get the SVG string.
# Start a local HTTP server in the demo directory
cd demo
python -m http.server 8080
pub fn render_chart(config_json : String) -> Stringmoon build --target wasm-gcpub trait Scale {
fn map(Self, Double) -> Double
fn ticks(Self, Int) -> Array[(Double, String)]
fn plotSize(Self) -> Double
}pub(all) struct BoxStats {
min : Double
q1 : Double
median : Double
q3 : Double
max : Double
iqr : Double
lowerFence : Double
upperFence : Double
whiskerLow : Double
whiskerHigh : Double
outliers : Array[Double]
}fn CategoryScale::new(tickPositions : Array[Double], tickLabels : Array[String], plotPixels : Double) -> CategoryScalepub struct ChartOption {
width : Double
height : Double
margin : Margin
background : Color
title : String?
titleFont : Font
xAxis : AxisOption
yAxis : AxisOption
series : Array[Series]
legend : Bool
legendPosition : Position
legendFontSize : Double
barWidthRatio : Double
barGap : Double
fontFamily : String
}pub enum ChartType {
Bar
Line
Scatter
BoxPlot
}pub(all) struct Color {
r : Int
g : Int
b : Int
a : Int
}pub struct DataPoint {
x : Double
y : Double
error_y : ErrorValue?
error_x : ErrorValue?
label : String?
}pub(all) enum ErrorValue {
Symmetric(Double)
Asymmetric(Double, Double)
}pub struct Layout {
canvas : Rect
plot : Rect
xScale : CategoryScale
yScale : LinearScale
dodgeOffsets : Array[Double]
barWidth : Double
}pub struct LinearScale {
min : Double
max : Double
plotPixels : Double
}pub struct LogScale {
base : Double
min : Double
max : Double
plotPixels : Double
}pub(all) struct Margin {
top : Double
right : Double
bottom : Double
left : Double
}pub(all) enum PointShape {
Circle
Square
Triangle
Diamond
Cross
}pub(all) enum Position {
TopLeft
TopCenter
TopRight
BottomLeft
BottomCenter
BottomRight
Left
Right
}pub struct Rect {
x : Double
y : Double
w : Double
h : Double
}pub struct Series {
name : String
chartType : ChartType
data : Array[DataPoint]
color : Color?
lineWidth : Double
pointSize : Double
pointShape : PointShape
lineStyle : LineStyle
pointFill : Color?
barStroke : Color?
barStrokeWidth : Double
errorColor : Color?
errorLineWidth : Double
errorCapWidth : Double
boxGroups : Array[BoxGroup]
showOutliers : Bool
}let DEFAULT_ERROR_CAP_WIDTH : Doublelet DEFAULT_POINT_SIZE : Doublefn circle(cx~ : Double, cy~ : Double, r~ : Double, fill~ : String, stroke~ : String, strokeWidth~ : Double) -> Stringfn line(x1~ : Double, y1~ : Double, x2~ : Double, y2~ : Double, stroke~ : String, strokeWidth~ : Double) -> Stringfn polyline(points~ : String, stroke~ : String, strokeWidth~ : Double, fill~ : String) -> Stringfn rect(x~ : Double, y~ : Double, w~ : Double, h~ : Double, fill~ : String, stroke~ : String, strokeWidth~ : Double) -> Stringfn saveSvg(filename : String, svg : String) -> Result[Unit, String]fn svgOpen(width~ : Double, height~ : Double, bg~ : String) -> StringA statistical chart SVG generation library for MoonBit. Supports bar charts, line charts, scatter plots with error bars and multi-series rendering.
Dependencies