Charts: multi-axis support

import io.data2viz.charts.* import io.data2viz.charts.core.Padding import io.data2viz.charts.core.* import io.data2viz.charts.dimension.* import io.data2viz.charts.chart.* import io.data2viz.charts.chart.mark.* import io.data2viz.charts.layout.* import io.data2viz.charts.config.configs.* import io.data2viz.charts.config.* import io.data2viz.charts.core.CursorType import io.data2viz.math.* import io.data2viz.geom.* import io.data2viz.viz.* import kotlinx.datetime.Instant val width = 450.0 val height = 300.0 data class Value(val monthIndex: Int, val first: Double?, val second: Double?, val third: Double?) private val months = listOf("Jan.", "Feb.", "Mar.", "Apr.", "May", "Jun.", "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec.") val values = listOf( Value(2, 16.4, 16023.0, 551.0), Value(3, 18.2, 28216.0, 427.4), Value(4, 22.9, 36125.0, 399.9), Value(5, 23.3, 38002.0, 389.0), Value(6, 20.6, 44632.0, 388.2), Value(7, 15.9, 38227.0, 412.7), Value(8, 12.9, 32670.0, 445.5), Value(9, 12.4, 28476.0, 529.1), ) fun main() { // Creating and sizing the VizContainer val vc = newVizContainer().apply { size = Size(width, height) } vc.chart(values) { config { cursor { show = true type = CursorType.Vertical } } val monthDim = discrete( { months[domain.monthIndex] } ) val firstDim = quantitative( { domain.first } ) val secondDim = quantitative( { domain.second } ) val thirdDim = quantitative( { domain.third } ) bar(monthDim, thirdDim) { val color = config.mark.strokeColors[3] strokeColor = constant(color) strokeColorHighlight = constant(color) fill = constant(color.withAlpha(40.pct)) fillHighlight = constant(color.withAlpha(40.pct)) y { layoutPosition = LayoutPosition.Right fontColor = color strokeColor = color tickStroke = color enableGridLines = true gridLinesDashed = doubleArrayOf(2.0, 5.0) end = 600.0 max = 600.0 } } line(monthDim, firstDim) { val color = config.mark.strokeColors[0] curve = MarkCurves.Curved showMarkers = true strokeColor = constant(color) strokeColorHighlight = constant(color) strokeWidth = constant(2.0) y { fontWeight = FontWeight.BOLD strokeWidth = 2.0 tickStrokeWidth = 2.0 fontColor = color strokeColor = color tickStroke = color } } line(monthDim, secondDim) { val color = config.mark.strokeColors[6] showMarkers = true strokeColor = constant(color) strokeColorHighlight = constant(color) y { fontColor = color strokeColor = color tickStroke = color } } } }
pierre avatar

Sketch created by

pierre

Displaying 3 different Y axes in a same chart. Each of the 3 mark (a bar and 2 lines) share the same X dimension (monthDim) but use its own Y dimension hence creating 3 different Y axis. One of the 3 Y-axis (the one for the bar mark) is placed on the right with the layoutPosition property. Also note that each Y-axis is styled with the same colors as the Mark so it's easier to identify which axis correspond to which mark. Note: The 2 left Y-axes have no start or end values, these values are automatically computed based on the range of your dataset. The right Y-axis start value however is "0" because the mark (a bar mark) "baseline" property is "0".

comments

Gaetan Zoritchak