Sparkline
A sparkline: the run of a number in the room of a word, beside the number it belongs to. It has no axes, no legend and nothing to point at: it shows which way the number has gone, and a chart shows the rest.
import com.pantrixui.components.chart.sparkline.PantrixSparkline
- Values. The values are set out at even steps from the start of the line to its end. A line and an area are drawn between the least and the most of the values: the run fills the height it has. Bars are drawn from nought.
- Ends.
minis the value at the foot of the height andmaxthe one at its top: several runs read on one scale. A value past the ends is cut off at the box's edge. An end not given comes from the values and the reference line. - Curve.
curvesays how a line and an area go from one value to the next (ChartCurve): straight, rounded without going past the values, or in steps. Bars have no curve. - Last value.
markLast = truemarks the last value: a dot on a line and an area, and on bars the last bar in full colour and the others fainter. The last value is the last one that is a number. - Reference line.
referencedraws a dashed line behind the values, in the colour charts write in: a target, or where the run began. - Style.
stylegoes over the theme's sizes: the line's width (lineWidth), the gap between bars (barGap), the last value's dot (markerSize) and the reference line's width (markLineWidth). - Kind.
SparklineKind.Lineis a line,Areaa line faintly filled under it,Bara bar for each value. - A missing value. A value that is
null, or no number, is a gap in a line and an empty place among bars. - Size and colour. It is 96dp wide and 32dp tall unless the modifier says otherwise; it is drawn in
color, or else in the theme's first chart colour. - Direction. In a language read from right to left the first value stands at the right.
- Export.
exportputs a button over the chart: the chart is made, as it is on the screen and without the part that is pointed at or its tooltip, into a PNG, an SVG or a PDF file and handed to the app. - Automation.
Sparkline_<tagKey>.
Examples
Beside a number
At its plainest: beside a number, the run of that number over the last twelve weeks. Since the number and its name are written beside it, the run has nothing more to say to a screen reader (contentDescription = null).
val strings = PantrixTheme.strings
Row(
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
verticalAlignment = Alignment.CenterVertically
) {
Column {
PantrixText(text = "Visits", color = PantrixTheme.colors.textSecondary)
PantrixText(text = strings.decimal(SPARK_VISITS.last()), style = PantrixTheme.typography.title)
}
PantrixSparkline(values = SPARK_VISITS, tagKey = "plain")
}
private val SPARK_VISITS = listOf(8200, 8650, 8400, 9100, 9800, 9300, 10400, 10100, 11200, 11800, 11500, 12480)
Line, area, bars
The same values in three kinds: a line, a line filled under it, and bars. Bars start at nought; a line at the least value.
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg)) {
PantrixSparkline(values = SPARK_VISITS, contentDescription = "Visits, line", tagKey = "line")
PantrixSparkline(
values = SPARK_VISITS,
kind = SparklineKind.Area,
contentDescription = "Visits, area",
tagKey = "area"
)
PantrixSparkline(
values = SPARK_VISITS,
kind = SparklineKind.Bar,
contentDescription = "Visits, bars",
tagKey = "bar"
)
}
private val SPARK_VISITS = listOf(8200, 8650, 8400, 9100, 9800, 9300, 10400, 10100, 11200, 11800, 11500, 12480)
Missing values and under nought
The weeks with no measure (null) are a gap in the line; a single value with none before it and none after it is a dot. The bars of values under nought go down from nought.
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg)) {
PantrixSparkline(values = SPARK_GAPS, contentDescription = "A measure with missing weeks", tagKey = "gaps")
PantrixSparkline(
values = SPARK_BALANCE,
kind = SparklineKind.Bar,
contentDescription = "Monthly profit and loss",
tagKey = "balance"
)
}
private val SPARK_GAPS = listOf(12, 15, 14, null, null, 18, 21, 19, null, 24)
private val SPARK_BALANCE = listOf(64, 31, -12, -38, 22, 47, 58, 87)
Your own size and colour
The modifier gives the size, color the colour: a rising run in the success colour, a falling one in the danger colour, in a wider room.
val colors = PantrixTheme.colors
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg)) {
PantrixSparkline(
values = SPARK_VISITS,
modifier = Modifier.size(160.dp, 48.dp),
kind = SparklineKind.Area,
color = colors.success.color,
contentDescription = "Rising visits",
tagKey = "up"
)
PantrixSparkline(
values = SPARK_VISITS.reversed(),
modifier = Modifier.size(160.dp, 48.dp),
kind = SparklineKind.Area,
color = colors.danger.color,
contentDescription = "Falling visits",
tagKey = "down"
)
}
private val SPARK_VISITS = listOf(8200, 8650, 8400, 9100, 9800, 9300, 10400, 10100, 11200, 11800, 11500, 12480)
Curve, last value and target
curve says how the line goes from one value to the next: Smooth rounds it without going past the values, StepAfter holds each value until the next. markLast = true marks the last value with a dot; on bars the last bar is drawn in full colour and the others fainter. reference draws a dashed line behind: here 20 degrees for the temperature, and the daily target for the orders.
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg)) {
PantrixSparkline(
values = SPARK_TEMPERATURE,
contentDescription = "Today's temperature",
tagKey = "smooth",
curve = ChartCurve.Smooth,
markLast = true,
reference = 20
)
PantrixSparkline(
values = SPARK_TEMPERATURE,
contentDescription = "Today's temperature, in steps",
tagKey = "steps",
curve = ChartCurve.StepAfter,
markLast = true
)
PantrixSparkline(
values = SPARK_ORDERS,
kind = SparklineKind.Bar,
contentDescription = "This week's orders",
tagKey = "orders",
markLast = true,
reference = 40
)
}
private val SPARK_TEMPERATURE = listOf(12.5, 11.8, 13.2, 16.4, 19.8, 22.6, 24.1, 23.4, 21.0, 18.2, 16.9, 15.7)
private val SPARK_ORDERS = listOf(32, 45, 38, 51, 29, 47, 43)
A shared scale and your own style
min and max give the ends of the height: two servers' processor use on one scale, from nought to a hundred. One is barely working, the other is full; with no ends given each would stand between its own least and most value, and both would look as high. The dashed line in both is the warning threshold at eighty percent (reference). style makes the line thicker and the last value's dot larger.
val style = ChartStyle(lineWidth = 3.dp, markerSize = 10.dp)
val servers = listOf(Triple("Server A", SPARK_QUIET, "quiet"), Triple("Server B", SPARK_BUSY, "busy"))
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
servers.forEach { (name, load, key) ->
Row(
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.md),
verticalAlignment = Alignment.CenterVertically
) {
PantrixText(text = name, modifier = Modifier.width(80.dp))
PantrixSparkline(
values = load,
modifier = Modifier.size(160.dp, 40.dp),
contentDescription = "$name, processor use",
tagKey = key,
style = style,
markLast = true,
reference = 80,
min = 0,
max = 100
)
PantrixText(text = PantrixTheme.strings.percent(load.last() / 100.0))
}
}
}
private val SPARK_QUIET = listOf(12, 18, 15, 22, 19, 14, 25, 21, 17, 23)
private val SPARK_BUSY = listOf(71, 78, 84, 80, 92, 88, 95, 99, 90, 86)
Export
export = ChartExport(...) puts an export button over the chart: press it and choose the kind (PNG, SVG or PDF). The chart makes the file and hands it to onExport; below, its name and size show, and a PNG's picture, and "Save the file" hands it over in the platform's way.
A small line is exported too: the button stands over the line, and the file is the line alone.
var file by remember { mutableStateOf<ChartExportFile?>(null) }
PantrixSparkline(
values = SPARK_VISITS,
contentDescription = "Visits of the last twelve days",
tagKey = "exported",
export = ChartExport(fileName = "visits") { file = it }
)
ExportedFile(file, tagKey = "exported")
private val SPARK_VISITS = listOf(8200, 8650, 8400, 9100, 9800, 9300, 10400, 10100, 11200, 11800, 11500, 12480)
API
values
A sparkline: the run of a number in the room of a word, beside the number it belongs to. It has no axes, no legend and nothing to point at: it shows which way the number has gone, and a chart shows the rest.
| Parameter | Type | Default | What it is |
|---|---|---|---|
values | List<Number?> | the values, in the order they are read. | |
modifier | Modifier | Modifier | the sparkline's modifier. A size here is the sparkline's. |
kind | SparklineKind | SparklineKind.Line | whether the values are a line, an area or bars. |
color | Color | Color.Unspecified | the colour it is drawn in. |
contentDescription | String? | null | what the run is of, in a few words, for a screen reader. null leaves it out of what a screen reader reads. |
tagKey | String? | null | the sparkline's automation key: the sparkline is Sparkline_<tagKey>. |
export | ChartExport? | null | what lets the reader take the chart out of the app as a PNG, an SVG or a PDF: a button over the chart makes the file of it as it is and hands it over (see ChartExport). null, the chart has no such button. |
style | ChartStyle? | null | the sizes it is drawn in over the theme's: the line's width (lineWidth), the gap between two bars (barGap), the mark of the last value (markerSize) and the reference line's width (markLineWidth). |
curve | ChartCurve | ChartCurve.Linear | how a line or an area goes from one value to the next. Bars have none. |
markLast | Boolean | false | whether the last value is marked: a dot on a line or an area, as large as the style's markerSize, and on bars the last one in color and the rest in a quieter share of it. The last value is the last that is a number. |
reference | Number? | null | a value a dashed line is drawn across the sparkline at, behind its values, in the colour charts write in: a target, or where the run began. null draws none. |
min | Number? | null | the value at the sparkline's foot, or null for the least of its values. A number, and less than max. |
max | Number? | null | the value at its top, or null for the most of them. |
ChartStyle
A chart's geometry: how tall it is where nothing says, how thick its lines and how large its marks are, and the room between its parts; and whether its fills have textures besides their colours.
| Parameter | Type | Default | What it is |
|---|---|---|---|
height | Dp | Dp.Unspecified | How tall a chart's plot is, with its axes, where the chart's modifier gives it no height. A legend above or under the plot adds its own. |
lineWidth | Dp | Dp.Unspecified | The width of a series' line. |
markerSize | Dp | Dp.Unspecified | The width and height of the mark on a point. |
selectedMarkerSize | Dp | Dp.Unspecified | The same of the mark on the point that is pointed at. |
gridWidth | Dp | Dp.Unspecified | The width of the grid's lines, of the lines along the axes and of the line that marks the place pointed at. Zero draws none. |
labelGap | Dp | Dp.Unspecified | Between the plot and what is written beside it and under it, and between that and an axis' title. |
tickSpacing | Dp | Dp.Unspecified | The least room between two values marked along the axis of values: what decides how many are marked where the axis does not say. |
legendGap | Dp | Dp.Unspecified | Between the legend and the chart it stands beside. |
legendItemGap | Dp | Dp.Unspecified | Between one entry of the legend and the next. |
swatchSize | Dp | Dp.Unspecified | How wide the sample of a series is in the legend and in the tooltip: a short run of its line, or a patch of its fill. |
swatchGap | Dp | Dp.Unspecified | Between that sample and the name after it. |
tooltipShape | ShapeSpec | ShapeSpec.Unspecified | The tooltip's corners: a step of the brand's shape scale, or a fixed shape. |
tooltipHorizontalPadding | Dp | Dp.Unspecified | Between the tooltip's sides and what it holds. |
tooltipVerticalPadding | Dp | Dp.Unspecified | Between its top and bottom and what it holds, and between its heading and rows. |
tooltipGap | Dp | Dp.Unspecified | Between the place pointed at and the tooltip beside it. |
tooltipElevation | Dp | Dp.Unspecified | The tooltip's shadow. |
barGap | Dp | Dp.Unspecified | Between two bars that stand side by side at a place. Bars too thin for it stand closer. |
barMaxWidth | Dp | Dp.Unspecified | The widest a bar is, however much room its place has: a chart of three places is not three slabs. |
barRadius | Dp | Dp.Unspecified | How round the corners of a bar's end are, the end away from nought. |
sliceGap | Dp | Dp.Unspecified | Between two slices of a pie that lie side by side, the same from the pie's middle to its rim. |
selectedSliceOffset | Dp | Dp.Unspecified | How far the slice of a pie that is pointed at stands out past the pie's rim. The pie keeps this much room about itself, so that the slice has where to stand. |
gaugeWidth | Dp | Dp.Unspecified | How thick the arc of a gauge is. An arc is no thicker than half its radius. |
meterHeight | Dp | Dp.Unspecified | How tall the bar of a meter group is. |
trackerHeight | Dp | Dp.Unspecified | How tall the blocks of a status tracker are. |
bubbleMinSize | Dp | Dp.Unspecified | How far across the smallest bubble of a scatter chart is: a point whose size is nothing, or too little to be seen as an area, is still a point. |
bubbleMaxSize | Dp | Dp.Unspecified | How far across its largest bubble is: the one whose size is the most of the chart's. |
navigatorHeight | Dp | Dp.Unspecified | How tall the strip under a chart's plot is, on which the part of the chart that is in view is marked and moved, in a chart whose zoom has one: how wide, beside a plot whose places go down its side. |
barBandShare | Float | Float.NaN | How much of a place's band its bars take, more than nought and one at the most: the rest is the room between one place's bars and the next's. Bars are no wider than barMaxWidth all the same. |
markLineWidth | Dp | Dp.Unspecified | The width of a mark's line: a target, a limit, a day. Zero draws none, and the mark's words are written all the same. |
markBandAlpha | Float | Float.NaN | How much of its colour a mark's band is drawn in, from nought to one: a band lies behind the series, and is a tint. |
patterns | Boolean? | null | Whether the fills of a chart's series, slices and tiles are drawn with textures besides their colours, and its lines broken in turn (ChartPattern): what tells them apart for a reader who cannot tell the colours apart. Left out, as the system is set: on where it is set to tell things apart without colour, iOS's "Differentiate Without Color" and Android's colour correction, and off otherwise. |
nodeWidth | Dp | Dp.Unspecified | How wide a node of a sankey is. |
nodeGap | Dp | Dp.Unspecified | Between two nodes of a column of a sankey. |
Accessibility
- Screen reader. With a
contentDescriptionit is a picture of that name; with none it is not read at all: that suits a run beside a number that says the same.