以前書いた記事のコメント で Flutter
だと CSS
のようにはグラデーションを書けない というやり取りをしました。
今回はなるべく CSS
に近いかたちでコーディングをしたいというテーマです。
🏹 TL;DR
結局、そのままでは書けなかったのでプラグイン作っちゃいましたw
background: linear-gradient(162.42deg, #FFE5C5 17.61%, #D2B38B 50.22%, #F1DDC3 83.52%);
このような CSS
を、
BoxDecoration(
gradient: linearGradient(162.42, ['#FFE5C5 17.61%', '#D2B38B 50.22%', '#F1DDC3 83.52%']),
);
Flutter
でこのように書くことができるようになります。
🎨 gradient_like_css
これが作成したプラグインです。
(実は初めて作りましたw)
pub.dev に公開しているので、よかったら使ってみてください。
インストール
pubspec.yaml
に依存関係を追加します。
dependencies:
gradient_like_css: ^1.0.0
Pub get
しましょう。
$ flutter pub get
使い方
インポートします。
import 'package:gradient_like_css/gradient_like_css.dart';
あとは BoxDecoration
の gradient
に linearGradient()
の結果を設定するだけ。
BoxDecoration(
gradient: linearGradient(-225, ['#69EACB', '#EACCF8 48%', "#6654F1"]),
);
第一引数の angleOrEndAlignment
には角度や Alignment
を指定できます。
第二引数の colorStopList
にはグラデーションの色や色経由点(開始点や終了点など)を指定できます。
CSS
に近いかたちにするために、文字列の List
にしています。
( Flutter
は可変長引数が使えないですからねぇ……)
詳しくはサンプルを見てみてください!
🌈 グラデーションのサンプル
CSS
の linear-gradient()
と同じグラデーションを作成するようにサンプルを作成しました。
元ネタは こちら です。
角度を指定しないグラデーション
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: linearGradient(null, ['#e66465', '#9198e5']),
),
);
angleOrEndAlignment
に null
を指定した場合、 CSS
の linear-gradient()
にあわせて 180°
(つまり下向き)のグラデーションになります。
色は #
始まりのカラーコードを使うことができます。
角度 45° のグラデーション
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: linearGradient(45, ['red', 'blue']),
),
);
角度は double
で指定できます。負の数や、 360
を超える数も使うことができます。
色はカラーコード以外にも、 X11/CSS3 color の色名も使うことができます。
開始点が 60% のグラデーション
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: linearGradient(135, ['orange', 'orange 60%', 'cyan']),
),
);
colorStopList
には色だけではなく stop
、つまりグラデーションの色経由点を指定できます。
上の例では orange
の開始点に 60%
を指定しています。
colorStopList
は半角スペースで区切った文字列のリストです。
複数の色経由点があるグラデーション
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: linearGradient(Alignment.centerRight,
['red 20%', 'orange 20% 40%', 'yellow 40% 60%', 'green 60% 80%', 'blue 80%']),
),
);
色経由点はふたつ指定することができ、隣り合う色に同じ色経由値を指定することで縞模様を作ることもできます。
(ぼくは使ったことがありませんが)
💡 開発したことによる気づき
Alignment
の反転は演算子でできる
LinearGradient
は begin
と end
に Alignment
を指定するのですが、このプラグインでは角度から Alignment
を生成しています。
角度で end
が決まり、必然的に begin
は逆方向になりますので、
final begin = Alignment(x, y);
// begin の逆向き
final end = Alignment(-x, -y)
のように書いていました。
でも実は Alignment
は演算子オーバーロードしているようで、
final begin = Alignment(x, y);
// begin の逆向き
final end = -begin;
のように書けるんです!
便利!!
double
の誤差には注意が必要
これも角度から Alignment
を生成する際に出くわしたのですが、 45°
のグラデーションと 405°
のグラデーションは同じものになるはずが、ユニットテストの結果 NG になってしまいました。
// 405° は (45° + 360°) で同じ方向のグラデーションになるはずがマッチしない……
expect(
linearGradient(45, ['red', 'blue']),
linearGradient(405, ['red', 'blue']),
);
原因は double
の誤差によるものでした。
演算をしている部分で丸め処理をしてやれば OK です。
ただ、丸め処理の書き方がわからず、
double.parse(math.sin(radians).toStringAsPrecision(8))
のような文字列を経由する格好の悪い書き方になっています…… 😇
良い書き方があれば教えて下さい!
🙇 まとめ
Flutter
で CSS
ライクに書けるようになりました!
(なんとも力技w)
プラグイン開発が初めてですし、英語は苦手(定期)、いろいろとボロボロな気がしますので、Qiita のコメントでもよいのでご意見いただけると嬉しいです 😋
(プルリクはもっと嬉しいです!!)