import io.data2viz.color.*
import io.data2viz.geom.*
import io.data2viz.math.*
import io.data2viz.viz.*
import io.data2viz.scale.*
import io.data2viz.axis.*
// Creating a quick data class for storing values
data class PlayerScore(val player:String, val score:Double)
// Let's add some values
val playerScores = listOf(
PlayerScore("Sandra", 74.6),
PlayerScore("John", 35.0),
PlayerScore("Mike", 96.5),
PlayerScore("June", 57.2),
PlayerScore("Freddy", 86.0),
PlayerScore("Vince", 40.8)
)
fun main() {
viz {
// Let's define the size of our visualization, and margins for axis
val dimension = 600.0
val margins = Margins(10.0, 10.0, 30.0, 70.0)
val chartWidth = dimension - margins.hMargins
val chartHeight = dimension - margins.vMargins
// Sizing the whole viz
size = size(dimension, dimension)
// Pretty much all visualizations are based on scales.
// Scales transform our raw values to dimensions, colors...
// Let's first create a scale to translate our values along the linear X-axis
val scoreScale = Scales.Continuous.linear {
// The concept of scale is to transform you DOMAIN values into your RANGE values
// We want to display our domain values (the "score") from 0 to 100
domain = listOf(.0, 100.0)
// Then map each of these values to a X-position on screen
// From the margin to the end of the viz
range = listOf(.0, chartWidth)
}
// Let's do the same for placing our categories along the X-axis
// Categories are discrete values, here we want to sort by our players names which are Strings
val playerScale = Scales.Discrete.band<String> {
// Just use some built-in kotlin function to retrieve all names
domain = playerScores.map { it.player }
// Then map these values to a continuous screen Y-position
range = StrictlyContinuous(.0, chartHeight)
// Band-scales are made for barcharts
// They allow placing bars and also defining the bars width using padding as a percentage
padding = 10.pct
}
// Now create a group for the bars
group {
transform {
translate(margins.left, margins.top)
}
// And just iterate over our values to create our bars
playerScores.forEach { playerScore ->
rect {
fill = Colors.Web.steelblue
// Scales are functions "(domain) -> range"
// So simply call them with your domain data
y = playerScale(playerScore.player)
// BandScale also provides the bandwidth for your chart
size = size(scoreScale(playerScore.score) - margins.left, playerScale.bandwidth)
}
}
}
// Place the X-axis (scores)
group {
transform {
translate(margins.left, dimension - margins.bottom)
}
axis(Orient.BOTTOM, scoreScale)
}
// Place the Y-axis (players)
group {
transform {
translate(margins.left, margins.top)
}
axis(Orient.LEFT, playerScale)
}
}.bindRendererOnNewCanvas()
}
comments