import io.data2viz.charts.*
import io.data2viz.charts.dimension.*
import io.data2viz.charts.chart.*
import io.data2viz.charts.chart.mark.*
import io.data2viz.charts.viz.*
import io.data2viz.charts.layout.*
import io.data2viz.charts.core.*
import io.data2viz.charts.core.Padding
import io.data2viz.geom.*
import io.data2viz.color.*
import io.data2viz.random.RandomDistribution
import kotlinx.datetime.Instant
import kotlinx.browser.document
import org.w3c.dom.*
val width = 900.0
val height = 480.0
fun main() {
// setting up the different accessors
val accessors: List<Datum<Sample>.() -> Double> = listOf(
{ domain.temperature },
{ domain.pressure },
{ domain.random }
)
// set a style for placing the CANVAS
val style = document.createElement("style")
style.innerHTML = "canvas{display:inline !important;}"
document.head!!.appendChild(style)
// creating the DIVs, then placing VizContainer inside
val charts = (0 until 3).map { xi ->
val div = document.createElement("div")
document.body!!.appendChild(div)
val chartrow = (0 until 3).map { yi ->
val vc = (div as HTMLDivElement).newVizContainer()
vc.apply {
size = Size(width / 3.0, height / 3.0)
}
vc.createChart(samples, accessors[yi], accessors[xi])
}
div.setAttribute("style", "height: ${height / 3.0}px;width: ${width}px")
chartrow
}
var current = 0
charts.forEachIndexed { xi, chartrow ->
chartrow.forEachIndexed { yi, chart ->
// "unlight" all
chart.onHighlight { _ ->
charts[0][0].highlight(listOf<Sample>())
charts[1][0].highlight(listOf<Sample>())
charts[2][0].highlight(listOf<Sample>())
charts[0][1].highlight(listOf<Sample>())
charts[1][1].highlight(listOf<Sample>())
charts[2][1].highlight(listOf<Sample>())
charts[0][2].highlight(listOf<Sample>())
charts[1][2].highlight(listOf<Sample>())
charts[2][2].highlight(listOf<Sample>())
}
// then highlight the expected one
(0 until 3).forEach { index ->
chart.onHighlight { evt -> charts[xi][index].highlight(evt.data) }
chart.onHighlight { evt -> charts[index][yi].highlight(evt.data) }
}
// also synchronize all "panning"
(0 until 9).forEach { index ->
if (index != current) {
chart.onPan { evt -> charts[index%3][index/3].pan(evt.panX, evt.panY) }
}
}
current++
}
}
}
private fun VizContainer.createChart(dataset:List<Sample>, xAcc: Datum<Sample>.() -> Double, yAcc: Datum<Sample>.() -> Double): Chart<Sample> {
return chart(dataset) {
config {
padding = Padding(2.0, 2.0, 2.0, 2.0)
events {
zoomMode = ZoomMode.None
panMode = PanMode.XY
}
cursor {
show = true
}
}
series = discrete( { domain.batchCode } )
val ts = quantitative( xAcc )
val tp = quantitative( yAcc )
plot(ts, tp) {
x {
enableTicksLabels = false
enableTicks = false
}
y {
enableTicksLabels = false
enableTicks = false
}
}
}
}
val randomGenerator = RandomDistribution(42).normal(100.0, 18.0)
data class Sample(
val sampleIndex: Int,
val batchCode: String,
val timestamp: Instant,
val temperature: Double,
val pressure: Double,
val random: Double,
)
val samples = generateSamples(200)
fun generateSamples(numSamples: Int) = (0 until numSamples).map {
val batchIndex = 1 + (it % 4)
val pressure: Double = randomGenerator() * 1000
val temp: Double = randomGenerator() * batchIndex * pressure / 100000
val ts = Instant.fromEpochMilliseconds(1611150127144L + (it * 8632L))
val random = randomGenerator() / temp
Sample(it, "Batch #$batchIndex", ts, temp, pressure, random)
}
comments