atmospheric_particles 0.3.5 copy "atmospheric_particles: ^0.3.5" to clipboard
atmospheric_particles: ^0.3.5 copied to clipboard

A lightweight and customizable Flutter package for creating beautiful particle animations and atmospheric effects in the background of any widget.

example/main.dart

import 'package:atmospheric_particles/atmospheric_particles.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const Sandbox(),
    );
  }
}

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

  @override
  State<Sandbox> createState() => _SandboxState();
}

class _SandboxState extends State<Sandbox> {
  double particleCount = 100;
  FadeDirection fadeDirection = FadeDirection.bottom;
  double minVertical = 100;
  double maxVertical = 200;
  double minHorizontal = 60;
  double maxHorizontal = 80;
  double trailLength = 0;

  late double _tempParticleCount;
  late double _tempMinVertical;
  late double _tempMaxVertical;
  late double _tempMinHorizontal;
  late double _tempMaxHorizontal;
  late double _tempTrailLength;

  @override
  void initState() {
    super.initState();
    _tempParticleCount = particleCount;
    _tempMinVertical = minVertical;
    _tempMaxVertical = maxVertical;
    _tempMinHorizontal = minHorizontal;
    _tempMaxHorizontal = maxHorizontal;
    _tempTrailLength = trailLength;
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    return Scaffold(
      backgroundColor: Colors.black,
      body: Column(
        children: [
          Expanded(
            child: AtmosphericParticles(
              key: ValueKey(
                '$particleCount-$fadeDirection-$minVertical-$maxVertical-$minHorizontal-$maxHorizontal-$trailLength',
              ),
              particleCount: particleCount.toInt(),
              fadeDirection: fadeDirection,
              minVerticalVelocity: minVertical,
              maxVerticalVelocity: maxVertical,
              minHorizontalVelocity: minHorizontal,
              maxHorizontalVelocity: maxHorizontal,
              particleColor: const Color(0xffff0000),
              trailLength: trailLength.toInt(),
              height: MediaQuery.of(context).size.height,
              child: const SizedBox(),
            ),
          ),
          Container(
            padding: const EdgeInsets.all(16),
            color: Colors.grey[900],
            child: SingleChildScrollView(
              child: Column(
                children: [
                  _buildSlider('Particle Count', _tempParticleCount, 10, 1000,
                      (val) {
                    setState(() => _tempParticleCount = val);
                  }, (val) {
                    setState(() => particleCount = val);
                  }),
                  _buildChips(
                      'Fade Direction', FadeDirection.values, fadeDirection,
                      (val) {
                    setState(() => fadeDirection = val);
                  }),
                  _buildSlider('Min Vertical', _tempMinVertical, -500, 500,
                      (val) {
                    setState(
                      () => _tempMinVertical = val.clamp(-500, maxVertical),
                    );
                  }, (val) {
                    setState(() => minVertical = val.clamp(-500, maxVertical));
                  }),
                  _buildSlider('Max Vertical', _tempMaxVertical, -500, 500,
                      (val) {
                    setState(
                      () => _tempMaxVertical = val.clamp(minVertical, 500),
                    );
                  }, (val) {
                    setState(() => maxVertical = val.clamp(minVertical, 500));
                  }),
                  _buildSlider('Min Horizontal', _tempMinHorizontal, -500, 500,
                      (val) {
                    setState(
                      () => _tempMinHorizontal = val.clamp(-500, maxHorizontal),
                    );
                  }, (val) {
                    setState(
                      () => minHorizontal = val.clamp(-500, maxHorizontal),
                    );
                  }),
                  _buildSlider('Max Horizontal', _tempMaxHorizontal, -500, 500,
                      (val) {
                    setState(
                      () => _tempMaxHorizontal = val.clamp(minHorizontal, 500),
                    );
                  }, (val) {
                    setState(
                      () => maxHorizontal = val.clamp(minHorizontal, 500),
                    );
                  }),
                  _buildSlider('Trail Length', _tempTrailLength, 0, 100, (val) {
                    setState(() => _tempTrailLength = val);
                  }, (val) {
                    setState(() => trailLength = val);
                  }),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSlider(
    String label,
    double value,
    double min,
    double max,
    ValueChanged<double> onChanged,
    ValueChanged<double> onChangeEnd,
  ) {
    return Row(
      children: [
        Text(label, style: const TextStyle(color: Colors.white)),
        Expanded(
          child: Slider(
            value: value,
            min: min,
            max: max,
            onChanged: onChanged,
            onChangeEnd: onChangeEnd,
          ),
        ),
        Text(
          value.toInt().toString(),
          style: const TextStyle(color: Colors.white),
        ),
      ],
    );
  }

  Widget _buildChips<T>(
    String label,
    List<T> options,
    T selected,
    ValueChanged<T> onSelected,
  ) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(label, style: const TextStyle(color: Colors.white)),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: options.map((option) {
            return ChoiceChip(
              selectedColor: Theme.of(context).primaryColor,
              showCheckmark: false,
              label: Text(
                option.toString().split('.').last,
                style: TextStyle(
                  color: option == selected ? Colors.white : Colors.black,
                ),
              ),
              selected: selected == option,
              onSelected: (_) => onSelected(option),
            );
          }).toList(),
        ),
      ],
    );
  }
}
6
likes
160
points
573
downloads

Publisher

unverified uploader

Weekly Downloads

A lightweight and customizable Flutter package for creating beautiful particle animations and atmospheric effects in the background of any widget.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on atmospheric_particles