Issue
How to create similar effect using Flutter?
Solution
I made a quick demo for you, tweak the Matrix4 params. (blur/depth of field doesn't work well on browser).
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
darkTheme:
ThemeData(platform: TargetPlatform.iOS, brightness: Brightness.dark),
home: RotationScene(),
);
}
}
class RotationScene extends StatefulWidget {
@override
_RotationSceneState createState() => _RotationSceneState();
}
class _RotationSceneState extends State<RotationScene> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'carrousel',
style: TextStyle(fontSize: 13),
),
centerTitle: false,
elevation: 12,
backgroundColor: Colors.transparent,
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xff74ABE4), Color(0xffA892ED)],
stops: [0, 1],
)),
child: Center(child: MyScener()),
),
);
}
}
class CardData {
Color color;
double x, y, z, angle;
final int idx;
double alpha = 0;
Color get lightColor {
var val = HSVColor.fromColor(color);
return val.withSaturation(.5).withValue(.8).toColor();
}
CardData(this.idx) {
color = Colors.primaries[idx % Colors.primaries.length];
x = 0;
y = 0;
z = 0;
}
}
class MyScener extends StatefulWidget {
@override
_MyScenerState createState() => _MyScenerState();
}
class _MyScenerState extends State<MyScener>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
List<CardData> cardData = [];
int numItems = 9;
double radio = 200.0;
double radioStep;
int centerIdx = 1;
@override
void initState() {
cardData = List.generate(numItems, (index) => CardData(index)).toList();
radioStep = (pi * 2) / numItems;
_animationController =
AnimationController(vsync: this, duration: Duration(seconds: 1));
_animationController.addListener(() => setState(() {}));
_animationController.addStatusListener((status) async {
if (status == AnimationStatus.completed) {
_animationController.value = 0;
_animationController.animateTo(1);
++centerIdx;
}
});
_animationController.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
var ratio = _animationController.value;
double animValue = centerIdx + ratio;
// process positions.
for (var i = 0; i < cardData.length; ++i) {
var c = cardData[i];
double ang = c.idx * radioStep + animValue;
c.angle = ang + pi / 2;
c.x = cos(ang) * radio;
// c.y = sin(ang) * 10;
c.z = sin(ang) * radio;
}
// sort in Z axis.
cardData.sort((a, b) => a.z.compareTo(b.z));
var list = cardData.map((vo) {
var c = addCard(vo);
var mt2 = Matrix4.identity();
mt2.setEntry(3, 2, 0.001);
mt2.translate(vo.x, vo.y, -vo.z);
mt2.rotateY(vo.angle + pi);
c = Transform(
alignment: Alignment.center,
origin: Offset(0.0, -0.0),
transform: mt2,
child: c,
);
// depth of field... doesnt work on web.
// var blur = .4 + ((1 - vo.z / radio) / 2) * 2;
// c = BackdropFilter(
// filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
// child: c,
// );
return c;
}).toList();
return Container(
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
children: list,
),
);
}
Widget addCard(CardData vo) {
var alpha = ((1 - vo.z / radio) / 2) * .6;
Widget c;
c = Container(
margin: EdgeInsets.all(12),
width: 120,
height: 80,
alignment: Alignment.center,
foregroundDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.black.withOpacity(alpha),
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0.1, .9],
colors: [vo.lightColor, vo.color],
),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(.2 + alpha * .2),
spreadRadius: 1,
blurRadius: 12,
offset: Offset(0, 2))
],
),
child: Text('ITEM ${vo.idx}'),
);
return c;
}
}
Answered By - roipeker
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.