Sanchit Batra
Sanchit Batra

Reputation: 49

CustomPainter making unnecessary connections between points flutter

I was trying to build a fourier series illustration I found and I was very close to completing when this weird problem occurred. The first illustration in this part of the wikipedia page is what I am trying to recreate. As you slide the slider forward it starts to approach a square wave pretty well. But abruptly, it starts to connect lines weirdly and make a mess out of it.

Here is the current code. The testing is what has to be called in the home of the MaterialApp:

import 'package:flutter/material.dart';
import "dart:math";

class Testing extends StatefulWidget {
  const Testing({super.key});

  @override
  State<Testing> createState() => _TestingState();
}

class _TestingState extends State<Testing> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;
  late double _value = 1;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: Duration(seconds: 5));
    _animation = Tween(begin: 2 * pi, end: 0.0).animate(_controller);
    _controller.forward();
    _controller.addListener(() {
      if (_animation.isCompleted) {
        _controller.reset();
        _controller.forward();
      }
      setState(() {});
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        Slider(
          min: 1,
          max: 100,
          divisions: 100,
          value: _value,
          onChanged: (new_value) => _value = new_value,
        ),
        SizedBox(
            height: 500,
            width: MediaQuery.sizeOf(context).width,
            child: ClipRRect(
              child: CustomPaint(
                painter: Sky(
                    angle: _animation.value,
                    running: _controller.isAnimating,
                    value: _value.toInt()),
                size: Size(MediaQuery.sizeOf(context).width, 500),
              ),
            )),
      ],
    ));
  }
}
List<Offset> wave = [];
class Sky extends CustomPainter {
  bool running;
  double angle;
  int value;
  Sky({required this.angle, required this.running, required this.value});
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()
      ..color = Colors.black
      ..strokeWidth = 1.0
      ..style = PaintingStyle.stroke;

    double centerX = 100;
    double centerY = size.height / 2;
    canvas.translate(centerX, centerY);

    double circleRadius = 80 * (4 / (1 * pi));
    double x1 = 0;
    double y1 = 0;
    for (int i = 0; i < value; i++) {
      double prevx = x1;
      double prevy = y1;
      int n = (i * 2) + 1;

      circleRadius = 80 * (4 / (n * pi));

      x1 += circleRadius * cos(n*angle);
      y1 += circleRadius * sin(n*angle);

      canvas.drawCircle(Offset(prevx, prevy), circleRadius, paint);

      canvas.drawLine(Offset(prevx, prevy), Offset(x1, y1), paint);
    }
    double waveValue = running ? y1 : 0;
    wave.insert(0, Offset(240, y1));
    // wave = wave.map((e) => e.translate(wave.indexOf(e).toDouble(), 0)).toList();

    if (running) {
      canvas.drawLine(Offset(x1, y1), Offset(240, y1), paint);
    }

    List<Offset> wave2 =
    wave.map((e) => e.translate(wave.indexOf(e).toDouble(), 0)).toList();
    // canvas.drawPoints(PointMode.lines, wave2, paint);
    Path path = Path();
    path.moveTo(wave2[0].dx, wave2[0].dy);
    for (int i = 1; i < wave2.length; i++) {
      path.lineTo(wave2[i].dx, wave2[i].dy);
    }
    for (int i = wave2.length-1; i > 1; i--) {
      path.lineTo(wave2[i].dx, wave2[i].dy);
    }
    canvas.drawPath(path, paint);
    if (wave.length > 1000) {
      wave.removeLast();
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

I have tried drawing the wave using drawPoints (all the point modes), draw vertices. I have also tried using for loops to individually draw lines from every one point in the wave2 list to every subsequent one but the problem persists. I want to figure out as to how I can use the list of points called wave2 and connect them to draw a wave.

Upvotes: 0

Views: 70

Answers (0)

Related Questions