Drafter
0.2.0indexedFlexible charting library enhancing visual representation with bar, line, pie, scatter, histogram, and waterfall charts. Customizable appearance, efficient rendering, and responsive design for diverse screen sizes.
Flexible charting library enhancing visual representation with bar, line, pie, scatter, histogram, and waterfall charts. Customizable appearance, efficient rendering, and responsive design for diverse screen sizes.
📊 A powerful, flexible charting library for Compose Multiplatform applications
Add the dependency below to your module's build.gradle file:
dependencies {
implementation("io.github.androidpoet:drafter:$drafter_version")
}
For Kotlin Multiplatform, add the dependency below to your module's build.gradle.kts file:
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.androidpoet:drafter:$drafter_version")
}
}
}
private fun getLineChartRenderer(colors: List<Color>) =
LineChartRenderer(
SimpleLineChartData(
labels = listOf(, , , ),
values = listOf(, , , ),
color = colors.first(),
),
)
{
LineChart(
renderer = getLineChartRenderer(colors = colors),
modifier = modifier.fillMaxSize(),
)
}
private fun getScatterPlotRenderer(colors: List<>) =
SimpleScatterPlotRenderer(
ScatterPlotData(
points =
List() {
Pair(
Random.nextFloat() * ,
Random.nextFloat() * ,
)
},
pointColors =
List() {
(colors.isNotEmpty()) colors[it % colors.size] Color.Gray
},
),
)
{
ScatterPlot(
modifier = Modifier.size(dp),
renderer = getScatterPlotRenderer(colors = colors),
)
}
private =
HeatmapRenderer(
ContributionHeatmapData(
baseColor = color,
contributions =
buildList {
now = Clock.System.now()
repeat() { day ->
date = now.minus(day.days)
count = (Random.nextFloat() > ) Random.nextInt(, )
add(ContributionData(date, count))
}
},
),
)
{
Heatmap(
renderer = getHeatmapRenderer(color = color),
modifier =
Modifier
.fillMaxWidth()
.height(dp),
)
}
@Composable
fun AreaChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
AreaChart(
renderer = AreaChartRenderer(
AreaChartData(
labels = listOf(, , , , , ),
values = listOf(, , , , , ),
color = colors[],
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
@Composable
fun StepLineChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
StepLineChart(
renderer = StepLineChartRenderer(
StepLineChartData(
labels = listOf("Mon", "Tue", , , ),
values = listOf(, , , , ),
color = colors[],
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
@Composable
fun BulletChartExample(colors: <>, modifier: = Modifier) {
BulletChart(
renderer = BulletChartRenderer(
BulletData(
metrics = listOf(
BulletMetric(, value = , target = , ranges = listOf(, , ), color = colors[]),
BulletMetric(, value = , target = , ranges = listOf(, , ), color = colors[]),
),
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
@Composable
fun FunnelChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
FunnelChart(
renderer = FunnelChartRenderer(
FunnelData(
stages = listOf(
FunnelStage(, , colors[]),
FunnelStage(, , colors[]),
FunnelStage(, , colors[]),
FunnelStage(, , colors[]),
),
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
@Composable
fun GaugeChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
GaugeChart(
renderer = GaugeChartRenderer(
GaugeData(value = 72f, min = 0f, max = 100f, label = "Score", color = colors[1]),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
@Composable
fun TreemapChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
TreemapChart(
renderer = TreemapChartRenderer(
TreemapData(
items = listOf(
TreemapItem(, , colors[]),
TreemapItem(, , colors[]),
TreemapItem(, , colors[]),
TreemapItem(, , colors[]),
),
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
@Composable
fun PolarAreaChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
PolarAreaChart(
renderer = PolarAreaChartRenderer(
PolarAreaData(
slices = listOf(
PolarSlice(, , colors[]),
PolarSlice(, , colors[]),
PolarSlice(, , colors[]),
PolarSlice(, , colors[]),
),
),
),
modifier = modifier.height(dp).fillMaxWidth(),
)
}
All charts read their palette and light/dark colors from DrafterTheme. Wrap your charts once to apply a consistent look (or supply a custom palette):
DrafterTheme(dark = isSystemInDarkTheme()) {
// charts here pick up LocalDrafterTheme
BarChart(renderer = renderer)
}
Every renderer also implements the shared ChartRenderer contract, so you can hold and pass them uniformly.
./gradlew :desktopApp:run — a scrollable gallery of all 27 charts../gradlew :webApp:wasmJsBrowserRun — the same gallery in the browser.Contributions are welcome! If you've found a bug, have an idea for an improvement, or want to contribute new features, please open an issue or submit a pull request.
Support it by joining stargazers for this repository. :star:
Also, follow me on GitHub for my next creations! 🤩
Designed and developed ()
Licensed under the Apache License, Version 2.0 ();
you may use except compliance the License.
You may obtain a copy of the License at
http:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.
DrafterTheme (light/dark, custom palettes)@Immutable data, layer-phase animations)private fun getBarChartData(colors: List<Color>) =
SimpleBarChartData(
labelsList = listOf("Jan", "Feb", "Mar", "Apr"),
values = listOf(10f, 30f, 15f, 45f),
colors = colors,
)
private fun getSimpleBarChartRenderer(colors: List<Color>) =
BarChartRenderer(getBarChartData(colors = colors))
fun SimpleBarChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
BarChart(
renderer = getSimpleBarChartRenderer(colors = colors),
modifier =
modifier
.height(300.dp)
.fillMaxWidth(),
animate = true,
)
}
private fun getBarChartRenderer() =
GroupedBarChartRenderer(
GroupedBarChartData(
labelsList = listOf("2020", "2021", "2022"),
itemNames = listOf("Product A", "Product B", "Product C"),
groupedValues =
listOf(
listOf(10f, 20f, 15f), // 2020
listOf(25f, 5f, 30f), // 2021
listOf(12f, 28f, 10f), // 2022
),
colors = listOf(Color.Red, Color.Green, Color.Blue),
),
)
fun GroupedBarChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
BarChart(
renderer = getBarChartRenderer(),
modifier =
Modifier
.height(300.dp)
.fillMaxWidth(),
animate = true,
)
}
private fun getStackedBarChartData(colors: List<Color>) =
StackedBarChartData(
labelsList = listOf("Q1", "Q2", "Q3"),
stacks =
listOf(
listOf(10f, 15f, 5f), // Q1
listOf(8f, 12f, 20f), // Q2
listOf(18f, 10f, 15f), // Q3
),
colors = colors,
)
private fun getStackedBarChartRenderer(colors: List<Color>) =
StackedBarChartRenderer(getStackedBarChartData(colors = colors))
fun StackedBarChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
BarChart(
renderer = getStackedBarChartRenderer(colors = colors),
modifier =
modifier
.height(300.dp)
.fillMaxWidth(),
animate = true,
)
}
private fun getGroupedLineChartData(colors: List<Color>) =
GroupedLineChartData(
labels = listOf("Q1", "Q2", "Q3", "Q4"),
itemNames = listOf("Product A", "Product B"),
groupedValues =
listOf(
listOf(10f, 15f),
listOf(20f, 25f),
listOf(15f, 10f),
listOf(25f, 20f),
),
colors = colors,
)
private fun getGroupedLineChartRenderer(colors: List<Color>) =
GroupedLineChartRenderer(getGroupedLineChartData(colors = colors))
fun GroupedLineChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
ChartContainer {
LineChart(
renderer = getGroupedLineChartRenderer(colors = colors),
modifier = modifier.fillMaxSize(),
)
}
}
private fun getStackedLineChartRenderer(colors: List<Color>) =
StackedLineChartRenderer(
StackedLineChartData(
labels = listOf("Jan", "Feb", "Mar", "Apr"),
stacks =
listOf(
listOf(5f, 5f, 2f),
listOf(7f, 3f, 4f),
listOf(6f, 4f, 3f),
listOf(8f, 2f, 5f),
),
colors = colors,
),
)
fun StackedLineChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
ChartContainer {
LineChart(
renderer = getStackedLineChartRenderer(colors = colors),
modifier = Modifier.fillMaxSize(),
)
}
}
private fun getHistogramData() = listOf(1f, 2f, 2f, 3f, 3f, 3f, 4f, 4f, 5f, 5f, 5f, 5f)
private fun getHistogramRenderer() =
HistogramRenderer(
dataPoints = getHistogramData(),
binCount = 5,
color = Color.Blue,
)
fun HistogramChartExample(
modifier: Modifier = Modifier,
animate: Boolean = true,
) {
BarChart(
renderer = getHistogramRenderer(),
modifier = modifier.size(300.dp),
animate = animate,
)
}
private fun getPieChartRenderer(colors: List<Color>) =
PieChartRenderer(
PieChartData(
slices =
listOf(
PieChartData.Slice(value = 40f, color = colors[0], label = "Red"),
PieChartData.Slice(value = 30f, color = colors[1], label = "Green"),
PieChartData.Slice(value = 20f, color = colors[2], label = "Blue"),
PieChartData.Slice(value = 10f, color = colors[3], label = "Purple"),
),
),
)
private fun getDonutPieChartRenderer(colors: List<Color>) =
DonutChartRenderer(
PieChartData(
slices =
listOf(
PieChartData.Slice(value = 40f, color = colors[0], label = "Red"),
PieChartData.Slice(value = 30f, color = colors[1], label = "Green"),
PieChartData.Slice(value = 20f, color = colors[2], label = "Blue"),
PieChartData.Slice(value = 10f, color = colors[3], label = "Purple"),
),
),
)
fun PieChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
PieChart(
renderer = getPieChartRenderer(colors = colors),
modifier = Modifier.size(200.dp),
animate = true,
)
}
fun DonutChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
PieChart(
renderer = getDonutPieChartRenderer(colors = colors),
modifier = Modifier.size(200.dp),
animate = true,
)
}
private fun getWaterfallChartRenderer(colors: List<Color>) =
WaterfallChartRenderer(
WaterfallChartData(
labelsList = listOf("Start", "Revenue", "Cost", "Profit"),
values = listOf(+50f, -20f, +30f), // Changes from 'Start'
colors = colors,
initialValue = 100f, // Start from 100
),
)
fun WaterfallChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
BarChart(
renderer = getWaterfallChartRenderer(colors = colors),
modifier =
modifier
.height(300.dp)
.fillMaxWidth(),
animate = true,
)
}
private fun getRadarRenderer(colors: List<Color>) =
RadarChartRenderer(
data =
listOf(
RadarChartData(
mapOf(
"Execution" to 0.8f,
"Landing" to 0.6f,
"Difficulty" to 0.9f,
"Style" to 0.7f,
"Creativity" to 0.85f,
),
),
),
colors = colors,
)
fun RadarChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
RadarChart(
modifier = modifier.size(300.dp),
renderer = getRadarRenderer(colors),
isSystemInDarkTheme = isSystemInDarkTheme()
)
}
private fun getGanttChartRenderer(colors: List<Color>) =
GanttChartRenderer(
GanttChartData(
taskColors = colors,
tasks =
listOf(
GanttTask("Planning", 0f, 2f),
GanttTask("Design", 2f, 2f),
GanttTask("Development", 4f, 3f),
GanttTask("Testing", 7f, 2f),
GanttTask("Deployment", 9f, 1f),
),
),
)
fun GanttChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
GanttChart(
renderer = getGanttChartRenderer(colors = colors),
modifier = modifier.size(400.dp),
)
}
private fun getBubbleChartData(colors: List<Color>) =
BubbleChartData(
series =
listOf(
listOf(
BubbleChartData.BubbleData(10f, 26f, 30f, colors[0]),
BubbleChartData.BubbleData(26f, 30f, 60f, colors[0]),
BubbleChartData.BubbleData(26f, 46f, 45f, colors[0]),
),
listOf(
BubbleChartData.BubbleData(14f, 15f, 30f, colors[1]),
BubbleChartData.BubbleData(22f, 36f, 45f, colors[1]),
BubbleChartData.BubbleData(90f, 57f, 75f, colors[1]),
),
listOf(
BubbleChartData.BubbleData(8f, 9f, 90f, colors[2]),
BubbleChartData.BubbleData(20f, 57f, 45f, colors[2]),
BubbleChartData.BubbleData(40f, 50f, 60f, colors[2]),
),
listOf(
BubbleChartData.BubbleData(8f, 20f, 22.5f, colors[3]),
BubbleChartData.BubbleData(12f, 30f, 30f, colors[3]),
BubbleChartData.BubbleData(30f, 40f, 45f, colors[3]),
),
),
)
private fun getBubbleChartRenderer(colors: List<Color>) =
SimpleBubbleChartDataRenderer(getBubbleChartData(colors = colors))
fun BubbleChartExample(
colors: List<Color>,
modifier: Modifier = Modifier,
) {
BubbleChart(
renderer = getBubbleChartRenderer(colors = colors),
modifier = modifier.size(300.dp),
)
}
fun CandlestickChartExample(modifier: Modifier = Modifier) {
CandlestickChart(
renderer = CandlestickChartRenderer(
CandlestickData(
candles = listOf(
Candle("1", open = 20f, high = 30f, low = 16f, close = 26f),
Candle("2", open = 26f, high = 32f, low = 22f, close = 23f),
Candle("3", open = 23f, high = 28f, low = 18f, close = 27f),
Candle("4", open = 27f, high = 38f, low = 25f, close = 35f),
),
),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
fun BoxPlotChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
BoxPlotChart(
renderer = BoxPlotChartRenderer(
BoxPlotData(
groups = listOf(
BoxGroup("A", min = 5f, q1 = 18f, median = 28f, q3 = 38f, max = 52f, color = colors[2]),
BoxGroup("B", min = 10f, q1 = 22f, median = 30f, q3 = 41f, max = 48f, color = colors[0]),
BoxGroup("C", min = 8f, q1 = 15f, median = 24f, q3 = 33f, max = 44f, color = colors[1]),
),
),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
fun SunburstChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
SunburstChart(
renderer = SunburstChartRenderer(
SunburstData(
roots = listOf(
SunburstNode(
"Web", 50f, colors[0],
children = listOf(
SunburstNode("HTML", 20f, colors[0]),
SunburstNode("CSS", 15f, colors[0]),
SunburstNode("JS", 15f, colors[0]),
),
),
SunburstNode(
"Mobile", 35f, colors[1],
children = listOf(
SunburstNode("iOS", 20f, colors[1]),
SunburstNode("Android", 15f, colors[1]),
),
),
),
),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
fun SankeyChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
SankeyChart(
renderer = SankeyChartRenderer(
SankeyData(
nodes = listOf(
SankeyNode("a", "Source A", column = 0, color = colors[0]),
SankeyNode("b", "Source B", column = 0, color = colors[1]),
SankeyNode("m", "Hub", column = 1, color = colors[2]),
SankeyNode("x", "Out X", column = 2, color = colors[3]),
SankeyNode("y", "Out Y", column = 2, color = colors[4]),
),
links = listOf(
SankeyLink("a", "m", 30f),
SankeyLink("b", "m", 20f),
SankeyLink("m", "x", 28f),
SankeyLink("m", "y", 22f),
),
),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
fun StreamGraphChartExample(colors: List<Color>, modifier: Modifier = Modifier) {
StreamGraphChart(
renderer = StreamGraphChartRenderer(
StreamData(
labels = listOf("Jan", "Feb", "Mar", "Apr", "May", "Jun"),
series = listOf(
StreamSeries("A", listOf(10f, 14f, 12f, 18f, 16f, 22f), colors[0]),
StreamSeries("B", listOf(8f, 10f, 16f, 12f, 18f, 14f), colors[1]),
StreamSeries("C", listOf(6f, 9f, 8f, 14f, 11f, 16f), colors[2]),
),
),
),
modifier = modifier.height(300.dp).fillMaxWidth(),
)
}
Surfaced from shared tags and platforms — no rankings paid for.