プログラミング

【Flutter】Aurora UIを実装する

2022年11月28日

2021年頃からトレンドになっている「Aurora UI」というUIデザインを、Flutterを使って実装してみたいと思います。

実装したもの

実装方法

Aurora UIは、

  1. 背景を用意する
  2. 背景をぼかす

ことで作成できるので、こちらの手順に沿って実装していきます。

背景を用意する

今回は下記のような円を複数重ね合わせた背景を用意します。

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

  • この記事を書いた人
  • 最新記事

おみ

プログラミング学習やキャリアのことを発信していきます。【経歴】1999年生まれ。専門学校卒業後、大手企業やベンチャー企業でSEとして勤務。現在は某メガベンチャーでFlutterエンジニアとして働いています。

-プログラミング
-, , ,