Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ColumnSeries not displayed correctly, have bug based on different data #2211

Closed
ImanGhasemiArani opened this issue Dec 17, 2024 · 6 comments
Closed
Labels
charts Charts component solved Solved the query using existing solutions

Comments

@ImanGhasemiArani
Copy link

ImanGhasemiArani commented Dec 17, 2024

Bug description

see test record

Steps to reproduce

see test 1 and 2 and their data.
but see test 3.

test 3 is correct, but test 1 and 2 are not correct in displaying the chart.
The current problem is that the bars are shown in different sizes in each case. Here I gave 3 data sets as an example. Which is what I expect is the last one. In the first and second cases, the bars are too big and this is not acceptable.
I want the bars to be displayed as in the third case, no matter how many data I give to the chart.

Code sample

Test 1 (bug)
series: [
        ColumnSeries<ChartData, double>(
          animationDuration: 1500,
          dataSource: [
            ChartData(x: 0, y: 95),
            ChartData(x: 10, y: 100),
            ChartData(x: 23, y: 93),
          ],
          xValueMapper: (data, _) => data.x.toDouble(),
          yValueMapper: (data, _) => data.y,
          width: 0.5,
          borderRadius: widget.isRounded
              ? const BorderRadius.vertical(top: Radius.circular(50))
              : BorderRadius.zero,
          color: widget.color,
          pointColorMapper: (data, _) => widget.colorResolver?.call(data),
          gradient: widget.gradient
              ? LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [
                    widget.color!,
                    widget.color!.withOpacity(0.5),
                  ],
                )
              : null,
        ),
      ],
Test 2 (bug)
          dataSource: [
            ChartData(x: 0, y: 95),
            ChartData(x: 10, y: 100),
            ChartData(x: 13, y: 93),
            ChartData(x: 23, y: 93),
          ],
         
Test 3 (expected)
          dataSource: [
            ChartData(x: 0, y: 95),
            ChartData(x: 10, y: 100),
            ChartData(x: 11, y: 93),
            ChartData(x: 23, y: 93),
          ],
         

Screenshots or Video

Screenshots test 1 (bug)

image

Screenshots test 2 (bug)

image

Screenshots test 3 (expected)

image

Stack Traces

Stack Traces
-

On which target platforms have you observed this bug?

Android

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.24.5, on Ubuntu 23.04 6.5.0-14-generic, locale
    en_US.UTF-8)
    • Flutter version 3.24.5 on channel stable at
      /home/casper/snap/flutter/common/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision dec2ee5c1f (5 weeks ago), 2024-11-13 11:13:06 -0800
    • Engine revision a18df97ca5
    • Dart version 3.5.4
    • DevTools version 2.37.3

[✓] Android toolchain - develop for Android devices (Android SDK version
    36.0.0-rc1)
    • Android SDK at /home/casper/Development/Android/Sdk/
    • Platform android-35, build-tools 36.0.0-rc1
    • Java binary at: /home/casper/.jdks/jbr-17.0.9/bin/java
    • Java version OpenJDK Runtime Environment JBR-17.0.9+8-1166.2-nomod (build
      17.0.9+8-b1166.2)
    • All Android licenses accepted.

[✓] Android Studio (version 2024.2)
    • Android Studio at /opt/android-studio-2024.2.1.10-linux/android-studio
    • Flutter plugin version 82.0.3
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-12282718-b509.11)

[✓] IntelliJ IDEA Ultimate Edition (version 2024.1)
    • IntelliJ at /opt/JetBrains.IntelliJ.IDEA.2023.3.6/idea-IU-233.15026.9
    • Flutter plugin version 79.0.3
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.96.0)
    • VS Code at /usr/share/code
    • Flutter extension version 3.102.0

[✓] Connected device (1 available)
    • SM A042F (mobile) • R83W50FKG6Y • android-arm64 • Android 14 (API 34)

[✓] Network resources
    • All expected network resources are available.

• No issues found!
@VijayakumarMariappan VijayakumarMariappan added charts Charts component open Open labels Dec 17, 2024
@BPraveenBalu
Copy link
Contributor

BPraveenBalu commented Dec 20, 2024

Hi @ImanGhasemiArani ,

We have reviewed the mentioned behavior at our end and we recommend using the plotOffset property in the primary axis. This property provides additional padding at the start and end of the plot area, ensuring that the full column series is displayed correctly at both ends of the plot area.

Additionally, you can use the plotOffsetStart property to add padding at the start of the plot area and the plotOffsetEnd property to add padding at the end.

Code snippet:

SfCartesianChart(
  primaryXAxis: NumericAxis(
    minimum: 0,
    maximum: 23,
    plotOffset: 50,
    // Add space only to the start of the plot area
    // plotOffsetStart: 20
    // Add space only to the end of the plot area
    // plotOffsetEnd: 20
  ),
  series: [
    ColumnSeries(
      ...
    )
  ],
)

For further details, we have provided a link to the user guide (UG) documentation and included a demo and sample for your reference.

UG link: https://help.syncfusion.com/flutter/cartesian-charts/axis-customization#offset-the-rendering.
Demo and sample: 668443.zip

Regards,
Praveen balu.

@LavanyaGowtham2021 LavanyaGowtham2021 added waiting for customer response Cannot make further progress until the customer responds. and removed open Open labels Dec 20, 2024
@ImanGhasemiArani
Copy link
Author

ImanGhasemiArani commented Dec 20, 2024

hi @BPraveenBalu

Thank you for your response. But the problem is not showing part of the bar at the beginning and end of the chart. This problem is solved by what you said and I solved it before.
The current problem is that the bars are shown in different sizes in each case. Here I gave 3 data sets as an example. Which is what I expect is the last one. In the first and second cases, the bars are too big and this is not acceptable.
I want the bars to be displayed as in the third case, no matter how many data I give to the chart.

Regards,
Iman Ghasemi Arani

@BPraveenBalu
Copy link
Contributor

Hi @ImanGhasemiArani ,

In SfCartesianChart, the width property is used to change the width of the rectangle. The default value of the width is 0.7, and the value ranges from 0 to 1. The column segment width is calculated based on the number of series and axis visible range.

You can achieve the mentioned requirement by rendering the column series with the fixed width using the ColumnSeriesRenderer and Column Segment. To render all the Column Segment with equal width for given three set of data, you can render the custom Column Segment with the fixed width in the ColumnSeriesRenderer by creating a renderer using the onCreateRenderer callback.

Disclaimer: However, while rendering the Column Series with the fixed width, the Column Segment might overlap with the other Column Segment. Based on your requirement, you can modify the rendering logic.

Code snippet:

class MainApp extends StatefulWidget {
  const MainApp({super.key});
 
  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  late List<ChartData> _firstData;
  late List<ChartData> _secondData;
  late List<ChartData> _thirdData;
  late List<ChartData> _data;
  late ZoomPanBehavior _zoomPanBehavior;
 
  @override
  void initState() {

    _firstData = [
      ChartData(x: 0, y: 95),
      ChartData(x: 10, y: 100),
      ChartData(x: 13, y: 93),
      ChartData(x: 23, y: 93),
    ];

    _secondData = [
      ChartData(x: 0, y: 95),
      ChartData(x: 10, y: 100),
      ChartData(x: 23, y: 93),
    ];

    _thirdData = [
      ChartData(x: 0, y: 95),
      ChartData(x: 10, y: 100),
      ChartData(x: 11, y: 93),
      ChartData(x: 23, y: 93),
    ];
    _data = _firstData;
    _zoomPanBehavior = ZoomPanBehavior(
      enablePanning: true,
      zoomMode: ZoomMode.x,
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          actions: [
            TextButton(
                onPressed: () {
                  _data = _firstData;
                  setState(() {});
                },
                child: Text('Test Data 1')),
            TextButton(
                onPressed: () {
                  _data = _secondData;
                  setState(() {});
                },
                child: Text('Test Data 2')),
            TextButton(
                onPressed: () {
                  _data = _thirdData;
                  setState(() {});
                },
                child: Text('Test Data 3'))
          ],
        ),
        body: SizedBox(
          height: 500,
          child: SfCartesianChart(
            enableSideBySideSeriesPlacement: true,
            enableMultiSelection: true,
            plotAreaBorderWidth: 0.7,
            plotAreaBorderColor: Colors.grey,
            zoomPanBehavior: _zoomPanBehavior,
            primaryXAxis: NumericAxis(
              minimum: 0,
            ),
            primaryYAxis: NumericAxis(
              interval: 20,
              minimum: 0.0,
              maximum: 120.0,
            ),
            series: <CartesianSeries<ChartData, double>>[
              ColumnSeries<ChartData, double>(
                width: 0.25,
                dataSource: _data,
                animationDuration: 1000,
                xValueMapper: (ChartData sales, int index) => sales.x,
                yValueMapper: (ChartData sales, int index) => sales.y,
                onCreateRenderer: (series) {
                  return CustomColumnSeriesRenderer(color: Colors.red);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}
 
class CustomColumnSeriesRenderer
    extends ColumnSeriesRenderer<ChartData, double> {
  CustomColumnSeriesRenderer({required this.color});

  @override
  final Color color;

  @override
  ColumnSegment<ChartData, double> createSegment() {
    return CustomColumnSegment(color: color);
  }
}
 
class CustomColumnSegment extends ColumnSegment<ChartData, double> {
  CustomColumnSegment({required this.color});

  final Color color;
  final double width = 20;
  final double cornerRadius = 20; // Radius for top-left and top-right corners
 
  @override
  void onPaint(Canvas canvas) {
    final double centerX = segmentRect!.center.dx;
    final double left = centerX - (width / 2);
    final double right = centerX + (width / 2);
    final Paint paint = Paint();
 
    paint
      ..color = color
      ..style = PaintingStyle.fill;
 
    final RRect roundedRect = RRect.fromRectAndCorners(
      Rect.fromLTRB(left, segmentRect!.top, right, segmentRect!.bottom),
      topLeft: Radius.circular(cornerRadius),
      topRight: Radius.circular(cornerRadius),
    );
    canvas.drawRRect(roundedRect, paint);
  }
}

class ChartData {
  ChartData({required this.x, required this.y});
  final double x;
  final double y;
}

Demo:

Eqaul column width for different data

Additionally, we have attached the sample and demo below for your reference and you can modify the sample according to your needs. If you have further queries, please get back to us.

Sample file: 668443_same_column_width.zip

Regards,
Praveen balu.

@ImanGhasemiArani
Copy link
Author

Hi @BPraveenBalu
Thank you very much.
I will test this solution.
But with this method, for example, if I enter 30 data samples, I want the width of the columns to be automatically sized, which logically will be less than the standard width. In addition, I need that if the number of data is small, the width of the columns should not exceed my desired width. I hope I was able to convey my meaning correctly.

Regards,
Iman Ghasemi Arani

@BPraveenBalu
Copy link
Contributor

Hi @ImanGhasemiArani

We have validated your query and you can achieve the mentioned requirement using the onCreateRenderer callback in the ColumnSeriesRenderer and ColumnSegment.

In the onPaint method of the custom ColumnSegment, we calculated a custom rect with a fixed width and obtained the default segment rect with series width property. If the custom rect width is smaller than the default segment rect width, the default segment rect is rendered. Otherwise, the custom rect is rendered if it is smaller. we have attached code snippet for onPaint method below.

Code snippet:

@override
  void onPaint(Canvas canvas) {
    final double desiredWidth = width * series.width;
    final BorderRadius borderRadius = series.borderRadius;
    final double centerX = segmentRect!.center.dx;
    final double left = centerX - (desiredWidth / 2);
    final double right = centerX + (desiredWidth / 2);

    // Custom Rect calculation
    final RRect customRect = RRect.fromRectAndCorners(
      Rect.fromLTRB(left, segmentRect!.top, right, segmentRect!.bottom),
      topLeft: borderRadius.topLeft,
      topRight: borderRadius.topRight,
      bottomLeft: borderRadius.bottomLeft,
      bottomRight: borderRadius.bottomRight,
    );

    // Prefer customRect or segmentRect based on the width.
    if (segmentRect!.width > customRect.width) {
      segmentRect = customRect;
    }

    super.onPaint(canvas);
  }

Also, we have provided the demo and sample below for your reference and you can modify the sample according to your needs.

Demo:
Automatically update width for more data

Sample:

668443_column_width_responsive.zip

Regards,
Praveen balu.

@LavanyaGowtham2021
Copy link
Collaborator

Please reopen if you need further assistance on this.

@LavanyaGowtham2021 LavanyaGowtham2021 added solved Solved the query using existing solutions and removed waiting for customer response Cannot make further progress until the customer responds. labels Mar 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
charts Charts component solved Solved the query using existing solutions
Projects
None yet
Development

No branches or pull requests

4 participants