2021年頃からトレンドになっている「Aurora UI」というUIデザインを、Flutterを使って実装してみたいと思います。
実装したもの
実装方法
Aurora UIは、
- 背景を用意する
- 背景をぼかす
ことで作成できるので、こちらの手順に沿って実装していきます。
背景を用意する
今回は下記のような円を複数重ね合わせた背景を用意します。
import 'dart:ui';
import 'package:flutter/material.dart';
class CircleParameter {
CircleParameter({
this.left = 0,
this.top = 0,
required this.color,
required this.diameter,
});
final double left;
final double top;
final Color color;
final double diameter;
}
class AuroraContainer extends StatelessWidget {
const AuroraContainer({
Key? key,
this.width = double.infinity,
this.height = double.infinity,
this.baseColor = Colors.white,
this.circleParameters = const [],
}) : super(key: key);
final double width;
final double height;
final Color baseColor;
final List<CircleParameter> circleParameters;
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
color: baseColor,
child: Stack(
children: [
...circleParameters.map(
(CircleParameter p) {
return _circle(
left: p.left - p.diameter / 2,
top: p.top - p.diameter / 2,
color: p.color,
diameter: p.diameter,
);
},
),
],
),
);
}
Widget _circle({
required double left,
required double top,
required Color color,
required double diameter,
}) {
return Positioned(
left: left,
top: top,
child: ClipOval(
child: Container(
width: diameter,
height: diameter,
color: color,
),
),
);
}
}
使い方の例
AuroraContainer(
baseColor: Colors.white,
circleParameters: [
CircleParameter(
left: 0,
top: 100,
color: Colors.purple,
diameter: 800,
),
CircleParameter(
left: 0,
top: MediaQuery.of(context).size.height,
color: Colors.purpleAccent,
diameter: 800,
),
CircleParameter(
left: MediaQuery.of(context).size.width + 100,
top: MediaQuery.of(context).size.height / 2 + 100,
color: Colors.deepPurpleAccent,
diameter: 700,
),
],
)
背景をぼかす
BackdropFilterを利用すると、背景をぼかすことができます。
https://api.flutter.dev/flutter/widgets/BackdropFilter-class.html
aurora_container.dartのStackのchildlenの最後に以下を下記のようなフィルターを追加すると、背景をぼかすことができます。
ClipRRect(
child: BackdropFilter(
filter: filter ?? ImageFilter.blur(
sigmaX: 50,
sigmaY: 50,
),
child: Container(
color: filterColor ?? Colors.white.withOpacity(0),
),
),
)
全体像
class AuroraContainerSamplePage extends StatelessWidget {
const AuroraContainerSamplePage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AuroraContainer(
baseColor: Colors.white,
filter: ImageFilter.blur(
sigmaX: 75,
sigmaY: 75,
),
circleParameters: [
CircleParameter(
left: 0,
top: 100,
color: Colors.purple,
diameter: 800,
),
CircleParameter(
left: 0,
top: MediaQuery.of(context).size.height,
color: Colors.purpleAccent,
diameter: 800,
),
CircleParameter(
left: MediaQuery.of(context).size.width + 100,
top: MediaQuery.of(context).size.height / 2 + 100,
color: Colors.deepPurpleAccent,
diameter: 700,
),
],
);
}
}
class CircleParameter {
CircleParameter({
this.left = 0,
this.top = 0,
required this.color,
required this.diameter,
});
final double left;
final double top;
final Color color;
final double diameter;
}
class AuroraContainer extends StatelessWidget {
const AuroraContainer({
Key? key,
this.width = double.infinity,
this.height = double.infinity,
this.baseColor = Colors.white,
this.filter,
this.filterColor,
this.circleParameters = const [],
}) : super(key: key);
final double width;
final double height;
final Color baseColor;
final ImageFilter? filter;
final Color? filterColor;
final List<CircleParameter> circleParameters;
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
color: baseColor,
child: Stack(
children: [
...circleParameters.map(
(CircleParameter p) {
return _circle(
left: p.left - p.diameter / 2,
top: p.top - p.diameter / 2,
color: p.color,
diameter: p.diameter,
);
},
),
ClipRRect(
child: BackdropFilter(
filter: filter ??
ImageFilter.blur(
sigmaX: 50,
sigmaY: 50,
),
child: Container(
color: filterColor ?? Colors.white.withOpacity(0),
),
),
)
],
),
);
}
Widget _circle({
required double left,
required double top,
required Color color,
required double diameter,
}) {
return Positioned(
left: left,
top: top,
child: ClipOval(
child: Container(
width: diameter,
height: diameter,
color: color,
),
),
);
}
}
参考
https://goworkship.com/magazine/2021-trend-aurora-ui/#Aurora_UI