Skip to content

Instantly share code, notes, and snippets.

@SamadiPour
Forked from imaNNeo/main.dart
Created December 24, 2020 14:40

Revisions

  1. SamadiPour revised this gist Dec 24, 2020. 1 changed file with 53 additions and 25 deletions.
    78 changes: 53 additions & 25 deletions main.dart
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,8 @@

    import 'dart:async';
    import 'dart:math' as math;
    import 'dart:ui';

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

    void main() {
    runApp(MyApp());
    @@ -18,7 +17,7 @@ double randD(double min, double max) =>

    class Orbit {
    final List<Electron> electrons;
    final angle;
    double angle;

    Orbit({
    @required this.electrons,
    @@ -68,7 +67,10 @@ class Electron {

    static Electron random() {
    const colors = [
    Colors.greenAccent, Colors.redAccent, Colors.cyanAccent, Colors.purpleAccent,
    Colors.greenAccent,
    Colors.redAccent,
    Colors.cyanAccent,
    Colors.purpleAccent,
    Colors.yellowAccent,
    ];
    final size = randD(5, 7);
    @@ -107,6 +109,7 @@ class HomePage extends StatefulWidget {
    }

    class _HomePageState extends State<HomePage> {
    final int _maxOrbitCount = 10;
    List<Orbit> _orbits = [
    Orbit(electrons: [], angle: 0.0),
    Orbit(electrons: [], angle: 60.0),
    @@ -121,18 +124,37 @@ class _HomePageState extends State<HomePage> {
    orbits: _orbits,
    ),
    ),
    floatingActionButton: FloatingActionButton(
    onPressed: () {
    setState(() {
    _orbits[math.Random().nextInt(_orbits.length)].electrons.add(Electron.random());
    });
    },
    child: Icon(Icons.add),
    floatingActionButton: InkWell(
    onLongPress: addOrbit,
    child: FloatingActionButton(
    onPressed: addElectron,
    child: Icon(Icons.add),
    ),
    ),
    );
    }
    }

    void addElectron() {
    setState(() {
    _orbits[math.Random().nextInt(_orbits.length)]
    .electrons
    .add(Electron.random());
    });
    }

    void addOrbit() {
    int count = _orbits.length + 1;
    if (count <= _maxOrbitCount) {
    final angelDifference = 180 / count;
    setState(() {
    _orbits
    .asMap()
    .forEach((index, orbit) => orbit.angle = angelDifference * index);
    _orbits.add(Orbit(electrons: [], angle: angelDifference * (count - 1)));
    });
    }
    }
    }

    class AtomWidget extends StatefulWidget {
    final List<Orbit> orbits;
    @@ -143,7 +165,8 @@ class AtomWidget extends StatefulWidget {
    _AtomWidgetState createState() => _AtomWidgetState();
    }

    class _AtomWidgetState extends State<AtomWidget> with SingleTickerProviderStateMixin {
    class _AtomWidgetState extends State<AtomWidget>
    with SingleTickerProviderStateMixin {
    Timer t;

    @override
    @@ -164,15 +187,15 @@ class _AtomWidgetState extends State<AtomWidget> with SingleTickerProviderStateM
    ...widget.orbits
    .map(
    (orbit) => Center(
    child: Transform.rotate(
    angle: degreesToRads(orbit.angle),
    child: CustomPaint(
    painter: _OrbitPainter(orbit),
    size: Size(atomSize, atomSize),
    child: Transform.rotate(
    angle: degreesToRads(orbit.angle),
    child: CustomPaint(
    painter: _OrbitPainter(orbit),
    size: Size(atomSize, atomSize),
    ),
    ),
    ),
    ),
    ),
    )
    )
    .toList(),
    Center(
    child: Container(
    @@ -214,7 +237,8 @@ class _OrbitPainter extends CustomPainter {
    final width = size.shortestSide;
    final height = width * 0.24;

    orbitPath.addOval(Rect.fromCenter(center: center, width: width, height: height));
    orbitPath
    .addOval(Rect.fromCenter(center: center, width: width, height: height));

    canvas.drawPath(
    orbitPath,
    @@ -225,11 +249,15 @@ class _OrbitPainter extends CustomPainter {
    );

    orbit.electrons.forEach((electron) {
    electron.currentSize = lerpDouble(electron.currentSize, electron.targetSize, 0.08);
    electron.currentColor = Color.lerp(electron.currentColor, electron.targetColor, 0.08);
    electron.currentSize =
    lerpDouble(electron.currentSize, electron.targetSize, 0.08);
    electron.currentColor =
    Color.lerp(electron.currentColor, electron.targetColor, 0.08);
    final degree = math.pi * 2 * electron.positionPercent;
    canvas.drawCircle(
    center + Offset(math.cos(degree) * (width / 2), math.sin(degree) * (height / 2)),
    center +
    Offset(math.cos(degree) * (width / 2),
    math.sin(degree) * (height / 2)),
    electron.currentSize / 2,
    Paint()
    ..color = electron.currentColor
  2. @imaNNeo imaNNeo created this gist Dec 23, 2020.
    245 changes: 245 additions & 0 deletions main.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,245 @@

    import 'dart:async';
    import 'dart:ui';

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

    void main() {
    runApp(MyApp());
    }

    num degreesToRads(num deg) {
    return (deg * math.pi) / 180.0;
    }

    double randD(double min, double max) =>
    math.Random().nextDouble() * (max - min) + min;

    class Orbit {
    final List<Electron> electrons;
    final angle;

    Orbit({
    @required this.electrons,
    @required this.angle,
    });
    }

    extension OrbitsExtension on List<Orbit> {
    void updateElectronsPosition() {
    this.forEach((orbit) {
    orbit.electrons.forEach((electron) {
    electron.move();
    });
    });
    }
    }

    class Electron {
    double speed;

    double currentSize;
    double targetSize;

    Color currentColor;
    Color targetColor;

    double _positionPercent = 0;

    double get positionPercent {
    return _positionPercent;
    }

    Electron({
    @required this.currentSize,
    @required this.targetSize,
    @required this.currentColor,
    @required this.targetColor,
    @required this.speed,
    });

    void move() {
    if (_positionPercent >= 1.0) {
    _positionPercent = 0;
    }
    _positionPercent += speed;
    }

    static Electron random() {
    const colors = [
    Colors.greenAccent, Colors.redAccent, Colors.cyanAccent, Colors.purpleAccent,
    Colors.yellowAccent,
    ];
    final size = randD(5, 7);
    final initialSize = size * 8;
    final color = colors[math.Random().nextInt(colors.length)];
    return Electron(
    currentSize: initialSize,
    targetSize: size,
    currentColor: color.withOpacity(0.1),
    targetColor: color,
    speed: randD(0.008, 0.012),
    );
    }
    }

    class MyApp extends StatelessWidget {
    // This widget is the root of your application.
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    title: 'Flutter Demo',
    theme: ThemeData(
    primarySwatch: Colors.yellow,
    visualDensity: VisualDensity.adaptivePlatformDensity,
    ),
    home: HomePage(),
    );
    }
    }

    class HomePage extends StatefulWidget {
    const HomePage({Key key}) : super(key: key);

    @override
    _HomePageState createState() => _HomePageState();
    }

    class _HomePageState extends State<HomePage> {
    List<Orbit> _orbits = [
    Orbit(electrons: [], angle: 0.0),
    Orbit(electrons: [], angle: 60.0),
    Orbit(electrons: [], angle: 120.0),
    ];

    Widget build(BuildContext context) {
    return Scaffold(
    backgroundColor: Color(0xFF191636),
    body: Center(
    child: AtomWidget(
    orbits: _orbits,
    ),
    ),
    floatingActionButton: FloatingActionButton(
    onPressed: () {
    setState(() {
    _orbits[math.Random().nextInt(_orbits.length)].electrons.add(Electron.random());
    });
    },
    child: Icon(Icons.add),
    ),
    );
    }
    }


    class AtomWidget extends StatefulWidget {
    final List<Orbit> orbits;

    const AtomWidget({Key key, @required this.orbits}) : super(key: key);

    @override
    _AtomWidgetState createState() => _AtomWidgetState();
    }

    class _AtomWidgetState extends State<AtomWidget> with SingleTickerProviderStateMixin {
    Timer t;

    @override
    void initState() {
    super.initState();
    t = Timer.periodic(Duration(milliseconds: 16), (timer) {
    setState(() {
    widget.orbits.updateElectronsPosition();
    });
    });
    }

    @override
    Widget build(BuildContext context) {
    final atomSize = (MediaQuery.of(context).size.shortestSide / 3) * 2;
    return Stack(
    children: [
    ...widget.orbits
    .map(
    (orbit) => Center(
    child: Transform.rotate(
    angle: degreesToRads(orbit.angle),
    child: CustomPaint(
    painter: _OrbitPainter(orbit),
    size: Size(atomSize, atomSize),
    ),
    ),
    ),
    )
    .toList(),
    Center(
    child: Container(
    width: atomSize / 10,
    height: atomSize / 10,
    decoration: BoxDecoration(
    shape: BoxShape.circle,
    gradient: LinearGradient(
    colors: [
    Color(0xffffc560),
    Color(0xffff593b),
    ],
    begin: Alignment.bottomLeft,
    end: Alignment.topRight,
    )),
    ),
    )
    ],
    );
    }

    @override
    void dispose() {
    t.cancel();
    super.dispose();
    }
    }

    class _OrbitPainter extends CustomPainter {
    final Orbit orbit;

    _OrbitPainter(this.orbit);

    @override
    void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    Path orbitPath = new Path();

    final width = size.shortestSide;
    final height = width * 0.24;

    orbitPath.addOval(Rect.fromCenter(center: center, width: width, height: height));

    canvas.drawPath(
    orbitPath,
    Paint()
    ..color = Color(0xFF26224f)
    ..style = PaintingStyle.stroke
    ..strokeWidth = 1,
    );

    orbit.electrons.forEach((electron) {
    electron.currentSize = lerpDouble(electron.currentSize, electron.targetSize, 0.08);
    electron.currentColor = Color.lerp(electron.currentColor, electron.targetColor, 0.08);
    final degree = math.pi * 2 * electron.positionPercent;
    canvas.drawCircle(
    center + Offset(math.cos(degree) * (width / 2), math.sin(degree) * (height / 2)),
    electron.currentSize / 2,
    Paint()
    ..color = electron.currentColor
    ..style = PaintingStyle.fill
    ..strokeCap = StrokeCap.round
    ..strokeWidth = electron.currentSize,
    );
    });
    }

    @override
    bool shouldRepaint(covariant _OrbitPainter oldDelegate) => true;
    }