newton_particles 0.1.0 copy "newton_particles: ^0.1.0" to clipboard
newton_particles: ^0.1.0 copied to clipboard

outdated

Create stunning animations with configurable particle emitters. Add rain, smoke, and more effects to your Flutter app!

example/lib/main.dart

import 'package:example/available_effect.dart';
import 'package:example/color_selection.dart';
import 'package:example/range_selection.dart';
import 'package:example/single_value_selection.dart';
import 'package:flutter/material.dart';
import 'package:newton_particles/newton_particles.dart';

void main() {
  runApp(const NewtonExampleApp());
}

class NewtonExampleApp extends StatelessWidget {
  const NewtonExampleApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    const Map<int, Color> primaryColor = {
      50: Color.fromRGBO(27, 27, 29, .1),
      100: Color.fromRGBO(27, 27, 29, .2),
      200: Color.fromRGBO(27, 27, 29, .3),
      300: Color.fromRGBO(27, 27, 29, .4),
      400: Color.fromRGBO(27, 27, 29, .5),
      500: Color.fromRGBO(27, 27, 29, .6),
      600: Color.fromRGBO(27, 27, 29, .7),
      700: Color.fromRGBO(27, 27, 29, .8),
      800: Color.fromRGBO(27, 27, 29, .9),
      900: Color.fromRGBO(27, 27, 29, 1),
    };
    return MaterialApp(
      themeMode: ThemeMode.dark,
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        primaryColor: const MaterialColor(
          0x1b1b1d,
          primaryColor,
        ),
        canvasColor: const Color(0xff1b1b1d),
      ),
      home: const NewtonConfigurationPage(),
    );
  }
}

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

  @override
  State<NewtonConfigurationPage> createState() =>
      _NewtonConfigurationPageState();
}

class _NewtonConfigurationPageState extends State<NewtonConfigurationPage> {
  final _scrollController = ScrollController();

  AvailableEffect _selectedAnimation = AvailableEffect.rain;
  EffectConfiguration _effectConfiguration =
      AvailableEffect.rain.defaultEffectConfiguration;
  ParticleColor _currentParticleColor =
      const SingleParticleColor(color: Colors.white);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          Newton(
            activeEffects: [currentActiveEffect()],
          ),
          configurationSection()
        ],
      ),
    );
  }

  Effect currentActiveEffect() {
    final size = MediaQuery.of(context).size;
    return _selectedAnimation.instantiate(
      size: size,
      effectConfiguration: _effectConfiguration,
      color: _currentParticleColor,
    );
  }

  Widget configurationSection() {
    return Scrollbar(
      controller: _scrollController,
      scrollbarOrientation: ScrollbarOrientation.left,
      child: SingleChildScrollView(
        controller: _scrollController,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const SizedBox(
                height: 20,
              ),
              animationSelectionSection(defaultAnimation: _selectedAnimation),
              const SizedBox(
                height: 20,
              ),
              if (_selectedAnimation.supportParameter(AnimationParameter.color))
                colorSelection(),
              const SizedBox(
                height: 20,
              ),
              particlesPerEmitSection(),
              emitDurationSection(),
              animationDurationSection(),
              if (_selectedAnimation
                  .supportParameter(AnimationParameter.distance))
                particleDistanceSection(),
              if (_selectedAnimation
                  .supportParameter(AnimationParameter.fadeout))
                particleFadeoutProgressSection(),
              particleBeginScaleSection(),
              particleEndScaleSection(),
              if (_selectedAnimation.supportParameter(AnimationParameter.angle))
                particleAngleSection(),
              if (_selectedAnimation
                  .supportParameter(AnimationParameter.trail)) ...[
                trailWidthSection(),
                trailProgressSection()
              ],
            ],
          ),
        ),
      ),
    );
  }

  Widget animationSelectionSection(
      {required AvailableEffect defaultAnimation}) {
    return SizedBox(
        width: 200,
        child: DropdownButton<String>(
          isExpanded: true,
          value: defaultAnimation.label,
          icon: const Icon(Icons.arrow_drop_down),
          elevation: 16,
          onChanged: (String? value) {
            // This is called when the user selects an item.
            setState(() {
              _selectedAnimation = AvailableEffect.of(value!);
              _effectConfiguration =
                  _selectedAnimation.defaultEffectConfiguration;
            });
          },
          items: AvailableEffect.values
              .map<DropdownMenuItem<String>>((AvailableEffect value) {
            return DropdownMenuItem<String>(
              value: value.label,
              child: Text(value.label),
            );
          }).toList(),
        ));
  }

  Widget animationDurationSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minDuration.toDouble(),
      initialMax: _effectConfiguration.maxDuration.toDouble(),
      min: 100,
      max: 8000,
      title: "Animation duration",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minDuration: values.start.round(),
            maxDuration: values.end.round(),
          );
        });
      },
    );
  }

  Widget particlesPerEmitSection() {
    return SingleValueSelection(
      value: _effectConfiguration.particlesPerEmit.toDouble(),
      title: "Particles per emit",
      onChanged: (value) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            particlesPerEmit: value.round(),
          );
        });
      },
      min: 1,
      max: 100,
    );
  }

  Widget emitDurationSection() {
    return SingleValueSelection(
      value: _effectConfiguration.emitDuration.toDouble(),
      title: "Emit duration",
      onChanged: (value) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            emitDuration: value.round(),
          );
        });
      },
      precision: 4,
      min: 100,
      max: 5000,
    );
  }

  Widget particleDistanceSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minDistance,
      initialMax: _effectConfiguration.maxDistance,
      min: 100,
      max: 2000,
      title: "Particle distance",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minDistance: values.start,
            maxDistance: values.end,
          );
        });
      },
    );
  }

  Widget particleFadeoutProgressSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minFadeOutThreshold,
      initialMax: _effectConfiguration.maxFadeOutThreshold,
      min: 0,
      max: 1,
      title: "Particle fadeout threshold",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minFadeOutThreshold: values.start,
            maxFadeOutThreshold: values.end,
          );
        });
      },
      roundValue: false,
    );
  }

  Widget particleBeginScaleSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minBeginScale,
      initialMax: _effectConfiguration.maxBeginScale,
      min: 0,
      max: 10,
      divisions: 100,
      title: "Particle begin scale",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minBeginScale: values.start,
            maxBeginScale: values.end,
          );
        });
      },
      roundValue: false,
    );
  }

  Widget particleEndScaleSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minEndScale,
      initialMax: _effectConfiguration.maxEndScale,
      min: 0,
      max: 10,
      divisions: 100,
      title: "Particle end scale",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minEndScale: values.start,
            maxEndScale: values.end,
          );
        });
      },
      roundValue: false,
    );
  }

  Widget particleAngleSection() {
    return RangeSelection(
      initialMin: _effectConfiguration.minAngle,
      initialMax: _effectConfiguration.maxAngle,
      min: -180,
      max: 180,
      divisions: 360,
      title: "Particle angle",
      onChanged: (values) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            minAngle: values.start,
            maxAngle: values.end,
          );
        });
      },
      precision: 3,
      roundValue: false,
    );
  }

  Widget trailProgressSection() {
    return SingleValueSelection(
      value: _effectConfiguration.trail.trailProgress,
      title: "Trail Progress",
      onChanged: (value) {
        setState(() {
          final trailWidth = _effectConfiguration.trail is NoTrail
              ? 0.0
              : (_effectConfiguration.trail as StraightTrail).trailWidth;
          _effectConfiguration = _effectConfiguration.copyWith(
            trail: StraightTrail(trailProgress: value, trailWidth: trailWidth),
          );
        });
      },
      roundValue: false,
      precision: 3,
      min: 0.0,
      max: 1.0,
    );
  }

  Widget trailWidthSection() {
    final trailWidth = _effectConfiguration.trail is NoTrail
        ? 0.0
        : (_effectConfiguration.trail as StraightTrail).trailWidth;
    return SingleValueSelection(
      value: trailWidth,
      title: "Trail Width",
      onChanged: (value) {
        setState(() {
          _effectConfiguration = _effectConfiguration.copyWith(
            trail: StraightTrail(
                trailProgress: _effectConfiguration.trail.trailProgress,
                trailWidth: value),
          );
        });
      },
      precision: 3,
      min: 0.0,
      max: 10,
    );
  }

  Widget colorSelection() {
    return ColorSelection(onChanged: (color) {
      setState(() {
        _currentParticleColor = color;
      });
    });
  }
}
110
likes
0
points
7.93k
downloads

Publisher

verified publisher7omtech.fr

Weekly Downloads

Create stunning animations with configurable particle emitters. Add rain, smoke, and more effects to your Flutter app!

Homepage

License

unknown (license)

Dependencies

flutter, vector_math

More

Packages that depend on newton_particles