Skip to content

Instantly share code, notes, and snippets.

@maheshmnj
Last active December 17, 2023 20:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save maheshmnj/d5cb45a3d73ebb1299c1f1206ee84425 to your computer and use it in GitHub Desktop.
Save maheshmnj/d5cb45a3d73ebb1299c1f1206ee84425 to your computer and use it in GitHub Desktop.
Ultra Gradient in Flutter
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return BackgroundWidget(
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
class BackgroundWidget extends StatefulWidget {
final Widget child;
const BackgroundWidget({super.key, required this.child});
@override
State<BackgroundWidget> createState() => _BackgroundWidgetState();
}
class _BackgroundWidgetState extends State<BackgroundWidget>
with SingleTickerProviderStateMixin {
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 6));
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
_controller.repeat(reverse: true);
super.initState();
}
@override
void dispose() {
_controller.removeStatusListener((status) {});
_controller.dispose();
super.dispose();
}
late AnimationController _controller;
late Animation<double> _animation;
@override
Widget build(BuildContext context) {
return Material(
child: Stack(
children: [
AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return CustomPaint(
painter: BackgroundPainter(
_animation,
),
child: Container(),
);
}),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 60, sigmaY: 60),
child: Container(
color: Colors.black.withOpacity(0.1),
)),
widget.child,
],
),
);
}
}
class BackgroundPainter extends CustomPainter {
final Animation<double> animation;
BackgroundPainter(this.animation);
Offset getOffset(Path path) {
final pms = path.computeMetrics(forceClosed: false).elementAt(0);
final length = pms.length;
final offset = pms.getTangentForOffset(length * animation.value)!.position;
return offset;
}
// Offset getOffset(Path path) {
// final pms = path.computeMetrics(forceClosed: false).elementAt(0);
// final length = pms.length;
// final offset = pms.getTangentForOffset(length * animation.value)!.position;
// return offset;
// }
void drawSquare(Canvas canvas, Size size) {
final paint1 = Paint();
paint1.color = Colors.blue.shade300;
paint1.maskFilter = MaskFilter.blur(BlurStyle.normal, 100);
paint1.style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset(size.width * 0.75, 100),
width: 300,
height: 300,
),
Radius.circular(20),
),
paint1);
}
void drawEllipse(Canvas canvas, Size size, Paint paint) {
final path = Path();
paint.color = Colors.purple;
paint.style = PaintingStyle.stroke;
path.moveTo(size.width * 0.4, -100);
path.quadraticBezierTo(size.width * 0.8, size.height * 0.6,
size.width * 1.2, size.height * 0.4);
// canvas.drawPath(path, paint);
paint.style = PaintingStyle.fill;
canvas.drawOval(
Rect.fromCenter(
center: getOffset(path),
width: 450,
height: 250,
),
paint);
}
void drawTriangle(Canvas canvas, Size size, paint) {
paint.color = Colors.green;
final path = Path();
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 10.0;
path.moveTo(-100.0, size.height * 0.5);
path.quadraticBezierTo(
300, size.height * 0.7, size.width, size.height * 1.2);
// canvas.drawPath(path, paint);
paint.style = PaintingStyle.fill;
// draw triangle
final offset = getOffset(path);
canvas.drawPath(
Path()
..moveTo(offset.dx, offset.dy)
..lineTo(offset.dx + 450, offset.dy + 150)
..lineTo(offset.dx + 250, offset.dy - 500)
..close(),
paint);
}
void drawCircle(Canvas canvas, Size size, Paint paint) {
paint.color = Colors.orange;
Path path = Path();
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 10.0;
path.moveTo(size.width * 1.1, size.height / 4);
path.quadraticBezierTo(
size.width / 2, size.height * 1.0, -100, size.height / 4);
// canvas.drawPath((path), paint);
paint.style = PaintingStyle.fill;
final offset = getOffset(path);
canvas.drawCircle(offset, 150, paint);
}
void drawAbstractShapes(Canvas canvas, Size size) {
Path path = Path();
final paint = Paint();
path.moveTo(size.width * 1.2, 0);
path.quadraticBezierTo(
size.width * 1.2, 300, size.width * 0.4, size.height * 0.6);
path.quadraticBezierTo(
size.width * 0.1, size.height * 0.7, -100, size.height * 1.2);
path.lineTo(-50, -50);
path.close();
paint.maskFilter = MaskFilter.blur(BlurStyle.normal, 100);
canvas.drawPath(
path,
paint
..color = Colors.purple.shade200
..style = PaintingStyle.fill);
drawSquare(canvas, size);
}
void drawContrastingBlobs(Canvas canvas, Size size, Paint paint) {
paint.maskFilter = MaskFilter.blur(BlurStyle.normal, 30);
paint.blendMode = BlendMode.overlay;
drawCircle(canvas, size, paint);
drawTriangle(canvas, size, paint);
drawEllipse(canvas, size, paint);
}
void paintBackground(Canvas canvas, Size size) {
canvas.drawRect(
Rect.fromCenter(
center: Offset(size.width * 0.5, size.height * 0.5),
width: size.width,
height: size.height,
),
Paint()..color = Colors.black);
}
@override
void paint(Canvas canvas, Size size) {
paintBackground(canvas, size);
drawAbstractShapes(canvas, size);
final paint = Paint();
drawContrastingBlobs(canvas, size, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment