Skip to content

The combo chart experiences lag when rendering five line series and five column series on large screen devices. #1025

Open
@phamquangsang

Description

@phamquangsang

Example

@Composable
private fun ComposeBasicComboChart(modelProducer: CartesianChartModelProducer, modifier: Modifier) {
  CartesianChartHost(
    rememberCartesianChart(
      rememberColumnCartesianLayer(
        ColumnCartesianLayer.ColumnProvider.series(
          colorList.map { color ->
            rememberLineComponent(fill = fill(color), thickness = 16.dp)
          }
        ),
      ),
      rememberLineCartesianLayer(
        LineCartesianLayer.LineProvider.series(
          colorList.map { color ->
            LineCartesianLayer.Line(
              fill = LineCartesianLayer.LineFill.single(fill(color)),
              dataLabel = TextComponent(
                color = color.toArgb(),
                textSizeSp = 12F,
              ),
              pointProvider = LineCartesianLayer.PointProvider.single(
                LineCartesianLayer.Point(
                  ShapeComponent(
                    fill = fill(Color.White),
                    strokeFill = fill(Color.Black),
                    strokeThicknessDp = 1F,
                    shape = CorneredShape.rounded(32f),
                  ),
                  sizeDp = 8f,
                ),
              ),
            )
          }

        ),
      ),
      startAxis = VerticalAxis.rememberStart(),
      bottomAxis = HorizontalAxis.rememberBottom(),
    ),
    modelProducer,
    modifier.height(400.dp),
    scrollState = rememberVicoScrollState(),
    zoomState = rememberVicoZoomState(),
  )
}
@Composable
internal fun BasicComboChart(uiFramework: UIFramework, modifier: Modifier) {
  val modelProducer = remember { CartesianChartModelProducer() }
  LaunchedEffect(Unit) {
    modelProducer.runTransaction {
      /* Learn more: https://patrykandpatrick.com/eji9zq. */
      columnSeries {
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
      }
      /* Learn more: https://patrykandpatrick.com/vmml6t. */
      lineSeries {
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
      }
    }
  }
  when (uiFramework) {
    UIFramework.Compose -> ComposeBasicComboChart(modelProducer, modifier)
    UIFramework.Views -> ViewBasicComboChart(modelProducer, modifier)
  }
}

private fun randomSeries(size: Int = 1000): List<Int> {
  val list = mutableListOf<Int>()
  for (i in 0 until size) {
    list.add(Random.nextInt(100))
  }
  return list
}

object ChartColors {
  val red = Color(0xFFEB4E3D)
  val orange = Color(0xFFF19A37)
  val yellow = Color(0xFFF7CE46)
  val green = Color(0xFF65C466)
  val mint = Color(0xFF5AC4BD)
  val teal = Color(0xFF5AAEC4)
  val cyan = Color(0xFF59ABE1)
  val blue = Color(0xFF3478F6)
  val indigo = Color(0xFF5856CE)
  val purple = Color(0xFFA357D7)
  val pink = Color(0xFFEB445A)
  val brown = Color(0xFF9D8563)
}
private val colorList = listOf<Color>(
  ChartColors.red,
  ChartColors.yellow,
  ChartColors.purple,
  ChartColors.green,
  ChartColors.blue,
)

https://github.com/user-attachments/assets/c9e1cf82-926b-4fa5-9b1a-7fc67b74ad86
https://github.com/user-attachments/assets/986b7964-6daa-4dc4-b2b8-72e007aef70e

How to reproduce

When rendering a combo chart with 5 lines and 5 columns, zoom and scroll enabled, on a Tablet device.

internal fun BasicComboChart(uiFramework: UIFramework, modifier: Modifier) {
  val modelProducer = remember { CartesianChartModelProducer() }
  LaunchedEffect(Unit) {
    modelProducer.runTransaction {
      /* Learn more: https://patrykandpatrick.com/eji9zq. */
      columnSeries {
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
      }
      /* Learn more: https://patrykandpatrick.com/vmml6t. */
      lineSeries {
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
        series(randomSeries())
      }
    }
  }
  when (uiFramework) {
    UIFramework.Compose -> ComposeBasicComboChart(modelProducer, modifier)
    UIFramework.Views -> ViewBasicComboChart(modelProducer, modifier)
  }
}

Each series contains 500 data points. 10 series in total

private fun randomSeries(size: Int = 500): List<Int> {
  val list = mutableListOf<Int>()
  for (i in 0 until size) {
    list.add(Random.nextInt(100))
  }
  return list
}

The chart has customized colors, visible data labels, and customized data points.

@Composable
private fun ComposeBasicComboChart(modelProducer: CartesianChartModelProducer, modifier: Modifier) {
  CartesianChartHost(
    rememberCartesianChart(
      rememberColumnCartesianLayer(
        ColumnCartesianLayer.ColumnProvider.series(
          colorList.map { color ->
            rememberLineComponent(fill = fill(color), thickness = 16.dp)
          }
        ),
      ),
      rememberLineCartesianLayer(
        LineCartesianLayer.LineProvider.series(
          colorList.map { color ->
            LineCartesianLayer.Line(
              fill = LineCartesianLayer.LineFill.single(fill(color)),
              dataLabel = TextComponent(
                color = color.toArgb(),
                textSizeSp = 12F,
              ),
              pointProvider = LineCartesianLayer.PointProvider.single(
                LineCartesianLayer.Point(
                  ShapeComponent(
                    fill = fill(Color.White),
                    strokeFill = fill(Color.Black),
                    strokeThicknessDp = 1F,
                    shape = CorneredShape.rounded(32f),
                  ),
                  sizeDp = 8f,
                ),
              ),
            )
          }

        ),
      ),
      startAxis = VerticalAxis.rememberStart(),
      bottomAxis = HorizontalAxis.rememberBottom(),
    ),
    modelProducer,
    modifier.height(400.dp),
    scrollState = rememberVicoScrollState(),
    zoomState = rememberVicoZoomState(),
  )
}

Observed behavior

The performance is very laggy when scrolling and zooming, even on high-end devices like the Galaxy Tab S9+ (Snapdragon 8 Gen 2). UI performance is significantly worse on tablet devices.

Expected behavior

zooming and scrolling should be smooth.

Module(s)

compose

Platform(s)

Android

Platform version(s)

Android 15

Vico version(s)

2.0.1

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions