Markers and labels
Markers draw a shape at each value of a series; labels render a data value next to each shape. Both are per-series config.
ts
// Markers draw a shape at each value of a line series; labels render the
// value of labelProperty next to each shape — point it at the series'
// own property to show value labels.
import type { MochartInputConfig } from '@mochart/core';
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Release Velocity' },
categoryAxis: { property: 'sprint', type: 'string', scale: 'ordinal' },
series: [
{
property: 'planned',
title: 'Planned',
renderer: 'bar',
labelProperty: 'planned',
labelFormat: ',.0f',
labelPosition: 'inside',
// Only the colors of the normal state are overridden — the opacities,
// the stroke width, and the focused/defocused states keep their defaults.
labelTextStyle: { normal: { strokeColor: '#ffffff', fillColor: '#ffffff' } },
labelMinRangeFraction: 0.05
},
{
property: 'shipped',
title: 'Shipped',
renderer: 'line',
markerShape: 'circle',
markerSize: 5
}
]
};
export const data = [
{ sprint: 'S1', planned: 12, shipped: 9 },
{ sprint: 'S2', planned: 14, shipped: 13 },
{ sprint: 'S3', planned: 11, shipped: 12 },
{ sprint: 'S4', planned: 15, shipped: 14 },
{ sprint: 'S5', planned: 13, shipped: 11 }
];How it works
markerShapepicks fromcircle,cross,diamond,square,star,triangle,wye;markerSizesets its size andmarkerStylepaints it — anormal/focused/defocusedset of stroke and fill colors, opacities and widths. PointmarkerPropertyat a data property to scale marker size per value — bubble charts.- Labels come from
labelProperty— point it at the series' ownproperty(as above) for value labels, or at any other data property.labelFormatformats the value ("auto"derives from the data). labelPositionplaces labelsinside,center, oroutsidethe shape, andlabelOffsetnudges every label by a fixed pixel amount along the series axis.- Three fraction guards hide labels that wouldn't fit:
labelMinRangeFraction(used above — it hides labels on bars shorter than 5% of the axis), andlabelMinPositionFraction/labelMaxPositionFraction, which hide labels whose values sit too close to the domain's minimum or maximum. labelPosition,labelOffset, and the two position-fraction guards each havelabelAboveBase*/labelBelowBase*variants (labelAboveBasePosition,labelBelowBaseOffset, …) that override them only for values above or below the series base — handy for labeling positive and negative bars differently. Their default'auto'inherits the base knob.labelTextStylepaints the label text, again per focus state. Its colors accept the palette modes (series,seriesIndex,categoryIndex) as well as literal colors — seecolorPalette. The example above sets onlylabelTextStyle.normal.strokeColorand.fillColor; every other member, including both other states, keeps its default.
Scatter and bubble charts
Markers on their own make a scatter chart: set renderer to none so a series draws no shape, and only its markers remain.
ts
// A scatter chart is marker-only series (renderer 'none') on a linear category
// axis, so points sit at their measured x values. Point markerProperty at a
// data property to scale marker size per point — a bubble chart.
import type { MochartInputConfig } from '@mochart/core';
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Latency under Load' },
categoryAxis: {
title: 'Requests per second',
property: 'load',
type: 'number',
scale: 'linear'
},
chart: {
margin: { right: 5 }
},
valueAxes: [{ id: 'VA0', title: 'Latency (ms)' }],
seriesDefaults: { renderer: 'none' },
series: [
{
property: 'v1',
title: 'v1',
markerShape: 'circle',
markerSize: 6
},
{
property: 'v2',
title: 'v2',
markerShape: 'diamond',
markerProperty: 'v2Errors',
markerMinSize: 4,
markerSize: 16
}
]
};
export const data = [
{ load: 12, v1: 38, v2: 31, v2Errors: 0 },
{ load: 45, v1: 42, v2: 33, v2Errors: 1 },
{ load: 70, v1: 55, v2: 41, v2Errors: 2 },
{ load: 160, v1: 74, v2: 52, v2Errors: 3 },
{ load: 240, v1: 92, v2: 60, v2Errors: 8 },
{ load: 310, v1: 121, v2: 71, v2Errors: 14 },
{ load: 470, v1: 168, v2: 95, v2Errors: 25 }
];- Use a
linearcategory axisscale(withnumberordatetype) so points are positioned by their measured x values rather than evenly spaced category slots. - For bubbles, point
markerPropertyat a data property; marker sizes scale betweenmarkerMinSizeandmarkerSizewith the property's value. markerSizeScalepicks how they scale: the defaultsqrtscales each marker's area with its value — the way readers judge bubble magnitude — whilelinearscales its diameter, which visually exaggerates differences. ThemarkerMinSizefloor keeps the smallest bubble visible (and hoverable); for exactly value-proportional areas, set it to0on data whose minimum is0.- Every series reads its x from the row's category value, so series share x positions. For series with points at different x values, give each x its own row and leave the other series' properties out — a row draws a marker only for the series that have a value there.