Make BoxDecoration lerp gradients (#12451)
This still is very limited in what it can lerp, but it sets the stage for arbitrary lerps later.
This commit is contained in:
parent
a13320253c
commit
1f82733a3b
@ -148,14 +148,13 @@ class BoxDecoration extends Decoration {
|
|||||||
|
|
||||||
/// Returns a new box decoration that is scaled by the given factor.
|
/// Returns a new box decoration that is scaled by the given factor.
|
||||||
BoxDecoration scale(double factor) {
|
BoxDecoration scale(double factor) {
|
||||||
// TODO(abarth): Scale ALL the things.
|
|
||||||
return new BoxDecoration(
|
return new BoxDecoration(
|
||||||
color: Color.lerp(null, color, factor),
|
color: Color.lerp(null, color, factor),
|
||||||
image: image,
|
image: image, // TODO(ianh): fade the image from transparent
|
||||||
border: BoxBorder.lerp(null, border, factor),
|
border: BoxBorder.lerp(null, border, factor),
|
||||||
borderRadius: BorderRadius.lerp(null, borderRadius, factor),
|
borderRadius: BorderRadius.lerp(null, borderRadius, factor),
|
||||||
boxShadow: BoxShadow.lerpList(null, boxShadow, factor),
|
boxShadow: BoxShadow.lerpList(null, boxShadow, factor),
|
||||||
gradient: gradient,
|
gradient: gradient?.scale(factor),
|
||||||
shape: shape,
|
shape: shape,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -165,6 +164,8 @@ class BoxDecoration extends Decoration {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
BoxDecoration lerpFrom(Decoration a, double t) {
|
BoxDecoration lerpFrom(Decoration a, double t) {
|
||||||
|
if (a == null)
|
||||||
|
return scale(t);
|
||||||
if (a is BoxDecoration)
|
if (a is BoxDecoration)
|
||||||
return BoxDecoration.lerp(a, this, t);
|
return BoxDecoration.lerp(a, this, t);
|
||||||
return super.lerpFrom(a, t);
|
return super.lerpFrom(a, t);
|
||||||
@ -172,6 +173,8 @@ class BoxDecoration extends Decoration {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
BoxDecoration lerpTo(Decoration b, double t) {
|
BoxDecoration lerpTo(Decoration b, double t) {
|
||||||
|
if (b == null)
|
||||||
|
return scale(1.0 - t);
|
||||||
if (b is BoxDecoration)
|
if (b is BoxDecoration)
|
||||||
return BoxDecoration.lerp(this, b, t);
|
return BoxDecoration.lerp(this, b, t);
|
||||||
return super.lerpTo(b, t);
|
return super.lerpTo(b, t);
|
||||||
@ -181,6 +184,16 @@ class BoxDecoration extends Decoration {
|
|||||||
///
|
///
|
||||||
/// Interpolates each parameter of the box decoration separately.
|
/// Interpolates each parameter of the box decoration separately.
|
||||||
///
|
///
|
||||||
|
/// The [shape] is not interpolated. To interpolate the shape, consider using
|
||||||
|
/// a [ShapeDecoration] with different border shapes.
|
||||||
|
///
|
||||||
|
/// If both values are null, this returns null. Otherwise, it returns a
|
||||||
|
/// non-null value. If one of the values is null, then the result is obtained
|
||||||
|
/// by applying [scale] to the other value. If neither value is null and `t ==
|
||||||
|
/// 0.0`, then `a` is returned unmodified; if `t == 1.0` then `b` is returned
|
||||||
|
/// unmodified. Otherwise, the values are computed by interpolating the
|
||||||
|
/// properties appropriately.
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Decoration.lerp], which can interpolate between any two types of
|
/// * [Decoration.lerp], which can interpolate between any two types of
|
||||||
@ -195,14 +208,17 @@ class BoxDecoration extends Decoration {
|
|||||||
return b.scale(t);
|
return b.scale(t);
|
||||||
if (b == null)
|
if (b == null)
|
||||||
return a.scale(1.0 - t);
|
return a.scale(1.0 - t);
|
||||||
// TODO(abarth): lerp ALL the fields.
|
if (t == 0.0)
|
||||||
|
return a;
|
||||||
|
if (t == 1.0)
|
||||||
|
return b;
|
||||||
return new BoxDecoration(
|
return new BoxDecoration(
|
||||||
color: Color.lerp(a.color, b.color, t),
|
color: Color.lerp(a.color, b.color, t),
|
||||||
image: t < 0.5 ? a.image : b.image,
|
image: t < 0.5 ? a.image : b.image, // TODO(ianh): cross-fade the image
|
||||||
border: BoxBorder.lerp(a.border, b.border, t),
|
border: BoxBorder.lerp(a.border, b.border, t),
|
||||||
borderRadius: BorderRadius.lerp(a.borderRadius, b.borderRadius, t),
|
borderRadius: BorderRadius.lerp(a.borderRadius, b.borderRadius, t),
|
||||||
boxShadow: BoxShadow.lerpList(a.boxShadow, b.boxShadow, t),
|
boxShadow: BoxShadow.lerpList(a.boxShadow, b.boxShadow, t),
|
||||||
gradient: t < 0.5 ? a.gradient : b.gradient,
|
gradient: Gradient.lerp(a.gradient, b.gradient, t),
|
||||||
shape: t < 0.5 ? a.shape : b.shape,
|
shape: t < 0.5 ? a.shape : b.shape,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -95,26 +95,26 @@ abstract class Decoration extends Diagnosticable {
|
|||||||
|
|
||||||
/// Linearly interpolates from `begin` to `end`.
|
/// Linearly interpolates from `begin` to `end`.
|
||||||
///
|
///
|
||||||
/// This defers to `end`'s [lerpTo] function if `end` is not null. If `end` is
|
/// This attempts to use [lerpFrom] and [lerpTo] on `end` and `begin`
|
||||||
/// null or if its [lerpTo] returns null, it uses `begin`'s [lerpFrom]
|
/// respectively to find a solution. If the two values can't directly be
|
||||||
/// function instead. If both return null, it attempts to lerp from `begin` to
|
/// interpolated, then the interpolation is done via null (at `t == 0.5`).
|
||||||
/// null if `t<0.5`, or null to `end` if `t≥0.5`.
|
///
|
||||||
|
/// If the values aren't null, then for `t == 0.0` and `t == 1.0` the values
|
||||||
|
/// `begin` and `end` are return verbatim.
|
||||||
static Decoration lerp(Decoration begin, Decoration end, double t) {
|
static Decoration lerp(Decoration begin, Decoration end, double t) {
|
||||||
Decoration result;
|
if (begin == null && end == null)
|
||||||
if (end != null)
|
return null;
|
||||||
result = end.lerpFrom(begin, t);
|
if (begin == null)
|
||||||
if (result == null && begin != null)
|
return end.lerpFrom(null, t) ?? end;
|
||||||
result = begin.lerpTo(end, t);
|
if (end == null)
|
||||||
if (result == null && begin != null && end != null) {
|
return begin.lerpTo(null, t) ?? begin;
|
||||||
if (t < 0.5) {
|
if (t == 0.0)
|
||||||
result = begin.lerpTo(null, t * 2.0);
|
return begin;
|
||||||
} else {
|
if (t == 1.0)
|
||||||
result = end.lerpFrom(null, (t - 0.5) * 2.0);
|
return end;
|
||||||
}
|
return end.lerpFrom(begin, t)
|
||||||
}
|
?? begin.lerpTo(end, t)
|
||||||
if (result == null)
|
?? (t < 0.5 ? begin.lerpTo(null, t * 2.0) : end.lerpFrom(null, (t - 0.5) * 2.0));
|
||||||
result = t < 0.5 ? begin : end;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether the given point, on a rectangle of a given size,
|
/// Tests whether the given point, on a rectangle of a given size,
|
||||||
|
@ -123,6 +123,13 @@ class FlutterLogoDecoration extends Decoration {
|
|||||||
///
|
///
|
||||||
/// Interpolates both the color and the style in a continuous fashion.
|
/// Interpolates both the color and the style in a continuous fashion.
|
||||||
///
|
///
|
||||||
|
/// If both values are null, this returns null. Otherwise, it returns a
|
||||||
|
/// non-null value. If one of the values is null, then the result is obtained
|
||||||
|
/// by scaling the other value's opacity and [margin]. If neither value is
|
||||||
|
/// null and `t == 0.0`, then `a` is returned unmodified; if `t == 1.0` then
|
||||||
|
/// `b` is returned unmodified. Otherwise, the values are computed by
|
||||||
|
/// interpolating the properties appropriately.
|
||||||
|
///
|
||||||
/// See also [Decoration.lerp].
|
/// See also [Decoration.lerp].
|
||||||
static FlutterLogoDecoration lerp(FlutterLogoDecoration a, FlutterLogoDecoration b, double t) {
|
static FlutterLogoDecoration lerp(FlutterLogoDecoration a, FlutterLogoDecoration b, double t) {
|
||||||
assert(a == null || a.debugAssertIsValid());
|
assert(a == null || a.debugAssertIsValid());
|
||||||
@ -151,6 +158,10 @@ class FlutterLogoDecoration extends Decoration {
|
|||||||
a._opacity * (1.0 - t).clamp(0.0, 1.0),
|
a._opacity * (1.0 - t).clamp(0.0, 1.0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (t == 0.0)
|
||||||
|
return a;
|
||||||
|
if (t == 1.0)
|
||||||
|
return b;
|
||||||
return new FlutterLogoDecoration._(
|
return new FlutterLogoDecoration._(
|
||||||
Color.lerp(a.lightColor, b.lightColor, t),
|
Color.lerp(a.lightColor, b.lightColor, t),
|
||||||
Color.lerp(a.darkColor, b.darkColor, t),
|
Color.lerp(a.darkColor, b.darkColor, t),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:math' as math;
|
||||||
import 'dart:ui' as ui show Gradient, lerpDouble;
|
import 'dart:ui' as ui show Gradient, lerpDouble;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -9,6 +10,30 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'alignment.dart';
|
import 'alignment.dart';
|
||||||
import 'basic_types.dart';
|
import 'basic_types.dart';
|
||||||
|
|
||||||
|
class _ColorsAndStops {
|
||||||
|
_ColorsAndStops(this.colors, this.stops);
|
||||||
|
final List<Color> colors;
|
||||||
|
final List<double> stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ColorsAndStops interpolateColorsAndStops(List<Color> aColors, List<double> aStops, List<Color> bColors, List<double> bStops, double t) {
|
||||||
|
assert(aColors.length == bColors.length, 'Cannot interpolate between two gradients with a different number of colors.'); // TODO(ianh): remove limitation
|
||||||
|
assert((aStops == null && aColors.length == 2) || (aStops != null && aStops.length == aColors.length));
|
||||||
|
assert((bStops == null && bColors.length == 2) || (bStops != null && bStops.length == bColors.length));
|
||||||
|
final List<Color> interpolatedColors = <Color>[];
|
||||||
|
for (int i = 0; i < aColors.length; i += 1)
|
||||||
|
interpolatedColors.add(Color.lerp(aColors[i], bColors[i], t));
|
||||||
|
List<double> interpolatedStops;
|
||||||
|
if (aStops != null || bStops != null) {
|
||||||
|
aStops ??= const <double>[0.0, 1.0];
|
||||||
|
bStops ??= const <double>[0.0, 1.0];
|
||||||
|
assert(aStops.length == bStops.length);
|
||||||
|
for (int i = 0; i < aStops.length; i += 1)
|
||||||
|
interpolatedStops.add(ui.lerpDouble(aStops[i], bStops[i], t).clamp(0.0, 1.0));
|
||||||
|
}
|
||||||
|
return new _ColorsAndStops(interpolatedColors, interpolatedStops);
|
||||||
|
}
|
||||||
|
|
||||||
/// A 2D gradient.
|
/// A 2D gradient.
|
||||||
///
|
///
|
||||||
/// This is an interface that allows [LinearGradient] and [RadialGradient]
|
/// This is an interface that allows [LinearGradient] and [RadialGradient]
|
||||||
@ -30,6 +55,73 @@ abstract class Gradient {
|
|||||||
/// it uses [AlignmentDirectional] objects instead of [Alignment]
|
/// it uses [AlignmentDirectional] objects instead of [Alignment]
|
||||||
/// objects, then the `textDirection` argument must not be null.
|
/// objects, then the `textDirection` argument must not be null.
|
||||||
Shader createShader(Rect rect, { TextDirection textDirection });
|
Shader createShader(Rect rect, { TextDirection textDirection });
|
||||||
|
|
||||||
|
/// Returns a new gradient with its properties scaled by the given factor.
|
||||||
|
///
|
||||||
|
/// A factor of 0.0 (or less) should result in a variant of the gradient that
|
||||||
|
/// is invisible; any two factors epsilon apart should be unnoticeably
|
||||||
|
/// different from each other at first glance. From this it follows that
|
||||||
|
/// scaling a gradient with values from 1.0 to 0.0 over time should cause the
|
||||||
|
/// gradient to smoothly disappear.
|
||||||
|
///
|
||||||
|
/// Typically this is the same as interpolating from null (with [lerp]).
|
||||||
|
Gradient scale(double factor);
|
||||||
|
|
||||||
|
/// Linearly interpolates from `a` to [this].
|
||||||
|
///
|
||||||
|
/// When implementing this method in subclasses, return null if this class
|
||||||
|
/// cannot interpolate from `a`. In that case, [lerp] will try `a`'s [lerpTo]
|
||||||
|
/// method instead.
|
||||||
|
///
|
||||||
|
/// If `a` is null, this must not return null. The base class implements this
|
||||||
|
/// by deferring to [scale].
|
||||||
|
///
|
||||||
|
/// Instead of calling this directly, use [Gradient.lerp].
|
||||||
|
@protected
|
||||||
|
Gradient lerpFrom(Gradient a, double t) {
|
||||||
|
if (a == null)
|
||||||
|
return scale(t);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Linearly interpolates from [this] to `b`.
|
||||||
|
///
|
||||||
|
/// This is called if `b`'s [lerpTo] did not know how to handle this class.
|
||||||
|
///
|
||||||
|
/// When implementing this method in subclasses, return null if this class
|
||||||
|
/// cannot interpolate from `b`. In that case, [lerp] will apply a default
|
||||||
|
/// behavior instead.
|
||||||
|
///
|
||||||
|
/// If `b` is null, this must not return null. The base class implements this
|
||||||
|
/// by deferring to [scale].
|
||||||
|
///
|
||||||
|
/// Instead of calling this directly, use [Gradient.lerp].
|
||||||
|
@protected
|
||||||
|
Gradient lerpTo(Gradient b, double t) {
|
||||||
|
if (b == null)
|
||||||
|
return scale(1.0 - t);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Linearly interpolates from `begin` to `end`.
|
||||||
|
///
|
||||||
|
/// This defers to `end`'s [lerpTo] function if `end` is not null. If `end` is
|
||||||
|
/// null or if its [lerpTo] returns null, it uses `begin`'s [lerpFrom]
|
||||||
|
/// function instead. If both return null, it returns `begin` before `t=0.5`
|
||||||
|
/// and `end` after `t=0.5`.
|
||||||
|
static Gradient lerp(Gradient begin, Gradient end, double t) {
|
||||||
|
Gradient result;
|
||||||
|
if (end != null)
|
||||||
|
result = end.lerpFrom(begin, t); // if begin is null, this must return non-null
|
||||||
|
if (result == null && begin != null)
|
||||||
|
result = begin.lerpTo(end, t); // if end is null, this must return non-null
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
if (begin == null && end == null)
|
||||||
|
return null;
|
||||||
|
assert(begin != null && end != null);
|
||||||
|
return t < 0.5 ? begin.scale(1.0 - (t * 2.0)) : end.scale((t - 0.5) * 2.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2D linear gradient.
|
/// A 2D linear gradient.
|
||||||
@ -173,9 +265,8 @@ class LinearGradient extends Gradient {
|
|||||||
/// Returns a new [LinearGradient] with its properties (in particular the
|
/// Returns a new [LinearGradient] with its properties (in particular the
|
||||||
/// colors) scaled by the given factor.
|
/// colors) scaled by the given factor.
|
||||||
///
|
///
|
||||||
/// If the factor is 1.0 or greater, then the gradient is returned unmodified.
|
|
||||||
/// If the factor is 0.0 or less, then the gradient is fully transparent.
|
/// If the factor is 0.0 or less, then the gradient is fully transparent.
|
||||||
/// Values in between scale the opacity of the colors.
|
@override
|
||||||
LinearGradient scale(double factor) {
|
LinearGradient scale(double factor) {
|
||||||
return new LinearGradient(
|
return new LinearGradient(
|
||||||
begin: begin,
|
begin: begin,
|
||||||
@ -186,6 +277,20 @@ class LinearGradient extends Gradient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpFrom(Gradient a, double t) {
|
||||||
|
if (a == null || (a is LinearGradient && a.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return LinearGradient.lerp(a, this, t);
|
||||||
|
return super.lerpFrom(a, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpTo(Gradient b, double t) {
|
||||||
|
if (b == null || (b is LinearGradient && b.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return LinearGradient.lerp(this, b, t);
|
||||||
|
return super.lerpTo(b, t);
|
||||||
|
}
|
||||||
|
|
||||||
/// Linearly interpolate between two [LinearGradient]s.
|
/// Linearly interpolate between two [LinearGradient]s.
|
||||||
///
|
///
|
||||||
/// If either gradient is null, this function linearly interpolates from a
|
/// If either gradient is null, this function linearly interpolates from a
|
||||||
@ -200,24 +305,13 @@ class LinearGradient extends Gradient {
|
|||||||
return b.scale(t);
|
return b.scale(t);
|
||||||
if (b == null)
|
if (b == null)
|
||||||
return a.scale(1.0 - t);
|
return a.scale(1.0 - t);
|
||||||
assert(a.colors.length == b.colors.length, 'Cannot interpolate between two gradients with a different number of colors.');
|
final _ColorsAndStops interpolated = interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t);
|
||||||
assert(a.stops == null || b.stops == null || a.stops.length == b.stops.length);
|
|
||||||
final List<Color> interpolatedColors = <Color>[];
|
|
||||||
for (int i = 0; i < a.colors.length; i += 1)
|
|
||||||
interpolatedColors.add(Color.lerp(a.colors[i], b.colors[i], t));
|
|
||||||
List<double> interpolatedStops;
|
|
||||||
if (a.stops != null && b.stops != null) {
|
|
||||||
for (int i = 0; i < a.stops.length; i += 1)
|
|
||||||
interpolatedStops.add(ui.lerpDouble(a.stops[i], b.stops[i], t));
|
|
||||||
} else {
|
|
||||||
interpolatedStops = a.stops ?? b.stops;
|
|
||||||
}
|
|
||||||
return new LinearGradient(
|
return new LinearGradient(
|
||||||
begin: AlignmentGeometry.lerp(a.begin, b.begin, t),
|
begin: AlignmentGeometry.lerp(a.begin, b.begin, t),
|
||||||
end: AlignmentGeometry.lerp(a.end, b.end, t),
|
end: AlignmentGeometry.lerp(a.end, b.end, t),
|
||||||
colors: interpolatedColors,
|
colors: interpolated.colors,
|
||||||
stops: interpolatedStops,
|
stops: interpolated.stops,
|
||||||
tileMode: t < 0.5 ? a.tileMode : b.tileMode,
|
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +497,58 @@ class RadialGradient extends Gradient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new [RadialGradient] with its colors scaled by the given factor.
|
||||||
|
///
|
||||||
|
/// If the factor is 0.0 or less, then the gradient is fully transparent.
|
||||||
|
@override
|
||||||
|
RadialGradient scale(double factor) {
|
||||||
|
return new RadialGradient(
|
||||||
|
center: center,
|
||||||
|
radius: radius,
|
||||||
|
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
|
||||||
|
stops: stops,
|
||||||
|
tileMode: tileMode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpFrom(Gradient a, double t) {
|
||||||
|
if (a == null || (a is RadialGradient && a.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return RadialGradient.lerp(a, this, t);
|
||||||
|
return super.lerpFrom(a, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Gradient lerpTo(Gradient b, double t) {
|
||||||
|
if (b == null || (b is RadialGradient && b.colors.length == colors.length)) // TODO(ianh): remove limitation
|
||||||
|
return RadialGradient.lerp(this, b, t);
|
||||||
|
return super.lerpTo(b, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Linearly interpolate between two [RadialGradient]s.
|
||||||
|
///
|
||||||
|
/// If either gradient is null, this function linearly interpolates from a
|
||||||
|
/// a gradient that matches the other gradient in [center], [radius], [stops] and
|
||||||
|
/// [tileMode] and with the same [colors] but transparent (using [scale]).
|
||||||
|
///
|
||||||
|
/// If neither gradient is null, they must have the same number of [colors].
|
||||||
|
static RadialGradient lerp(RadialGradient a, RadialGradient b, double t) {
|
||||||
|
if (a == null && b == null)
|
||||||
|
return null;
|
||||||
|
if (a == null)
|
||||||
|
return b.scale(t);
|
||||||
|
if (b == null)
|
||||||
|
return a.scale(1.0 - t);
|
||||||
|
final _ColorsAndStops interpolated = interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t);
|
||||||
|
return new RadialGradient(
|
||||||
|
center: AlignmentGeometry.lerp(a.center, b.center, t),
|
||||||
|
radius: math.max(0.0, ui.lerpDouble(a.radius, b.radius, t)),
|
||||||
|
colors: interpolated.colors,
|
||||||
|
stops: interpolated.stops,
|
||||||
|
tileMode: t < 0.5 ? a.tileMode : b.tileMode, // TODO(ianh): interpolate tile mode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(dynamic other) {
|
bool operator ==(dynamic other) {
|
||||||
if (identical(this, other))
|
if (identical(this, other))
|
||||||
|
@ -282,15 +282,14 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('BoxDecoration.lerp - gradients', () {
|
test('BoxDecoration.lerp - gradients', () {
|
||||||
// We don't lerp the gradients, we just switch from one to the other at t=0.5.
|
final Gradient gradient = const LinearGradient(colors: const <Color>[ const Color(0x00000000), const Color(0xFFFFFFFF) ]);
|
||||||
final Gradient gradient = new LinearGradient(colors: <Color>[ const Color(0x00000000), const Color(0xFFFFFFFF) ]);
|
|
||||||
expect(
|
expect(
|
||||||
BoxDecoration.lerp(
|
BoxDecoration.lerp(
|
||||||
const BoxDecoration(),
|
const BoxDecoration(),
|
||||||
new BoxDecoration(gradient: gradient),
|
new BoxDecoration(gradient: gradient),
|
||||||
-1.0,
|
-1.0,
|
||||||
),
|
),
|
||||||
const BoxDecoration()
|
const BoxDecoration(gradient: const LinearGradient(colors: const <Color>[ const Color(0x00000000), const Color(0x00FFFFFF) ]))
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
BoxDecoration.lerp(
|
BoxDecoration.lerp(
|
||||||
@ -306,7 +305,7 @@ void main() {
|
|||||||
new BoxDecoration(gradient: gradient),
|
new BoxDecoration(gradient: gradient),
|
||||||
0.25,
|
0.25,
|
||||||
),
|
),
|
||||||
const BoxDecoration()
|
const BoxDecoration(gradient: const LinearGradient(colors: const <Color>[ const Color(0x00000000), const Color(0x40FFFFFF) ]))
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
BoxDecoration.lerp(
|
BoxDecoration.lerp(
|
||||||
@ -314,7 +313,7 @@ void main() {
|
|||||||
new BoxDecoration(gradient: gradient),
|
new BoxDecoration(gradient: gradient),
|
||||||
0.75,
|
0.75,
|
||||||
),
|
),
|
||||||
new BoxDecoration(gradient: gradient)
|
const BoxDecoration(gradient: const LinearGradient(colors: const <Color>[ const Color(0x00000000), const Color(0xBFFFFFFF) ]))
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
BoxDecoration.lerp(
|
BoxDecoration.lerp(
|
||||||
|
@ -38,7 +38,6 @@ void main() {
|
|||||||
const Color(0x66666666),
|
const Color(0x66666666),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final LinearGradient testGradient2 = const LinearGradient(
|
final LinearGradient testGradient2 = const LinearGradient(
|
||||||
begin: Alignment.topRight,
|
begin: Alignment.topRight,
|
||||||
end: Alignment.topLeft,
|
end: Alignment.topLeft,
|
||||||
@ -47,8 +46,8 @@ void main() {
|
|||||||
const Color(0x88888888),
|
const Color(0x88888888),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final LinearGradient actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
|
|
||||||
|
|
||||||
|
final LinearGradient actual = LinearGradient.lerp(testGradient1, testGradient2, 0.5);
|
||||||
expect(actual, const LinearGradient(
|
expect(actual, const LinearGradient(
|
||||||
begin: const Alignment(0.0, -1.0),
|
begin: const Alignment(0.0, -1.0),
|
||||||
end: const Alignment(-1.0, 0.0),
|
end: const Alignment(-1.0, 0.0),
|
||||||
@ -152,4 +151,90 @@ void main() {
|
|||||||
returnsNormally,
|
returnsNormally,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('RadialGradient lerp test', () {
|
||||||
|
final RadialGradient testGradient1 = const RadialGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
radius: 20.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x33333333),
|
||||||
|
const Color(0x66666666),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final RadialGradient testGradient2 = const RadialGradient(
|
||||||
|
center: Alignment.topRight,
|
||||||
|
radius: 10.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x44444444),
|
||||||
|
const Color(0x88888888),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final RadialGradient actual = RadialGradient.lerp(testGradient1, testGradient2, 0.5);
|
||||||
|
expect(actual, const RadialGradient(
|
||||||
|
center: const Alignment(0.0, -1.0),
|
||||||
|
radius: 15.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x3B3B3B3B),
|
||||||
|
const Color(0x77777777),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Gradient lerp test (with RadialGradient)', () {
|
||||||
|
final RadialGradient testGradient1 = const RadialGradient(
|
||||||
|
center: Alignment.topLeft,
|
||||||
|
radius: 20.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x33333333),
|
||||||
|
const Color(0x66666666),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final RadialGradient testGradient2 = const RadialGradient(
|
||||||
|
center: const Alignment(0.0, -1.0),
|
||||||
|
radius: 15.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x3B3B3B3B),
|
||||||
|
const Color(0x77777777),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final RadialGradient testGradient3 = const RadialGradient(
|
||||||
|
center: Alignment.topRight,
|
||||||
|
radius: 10.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x44444444),
|
||||||
|
const Color(0x88888888),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient3, 0.0), testGradient1);
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient3, 0.5), testGradient2);
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient3, 1.0), testGradient3);
|
||||||
|
expect(Gradient.lerp(testGradient3, testGradient1, 0.0), testGradient3);
|
||||||
|
expect(Gradient.lerp(testGradient3, testGradient1, 0.5), testGradient2);
|
||||||
|
expect(Gradient.lerp(testGradient3, testGradient1, 1.0), testGradient1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Gradient lerp test (LinearGradient to RadialGradient)', () {
|
||||||
|
final LinearGradient testGradient1 = const LinearGradient(
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x33333333),
|
||||||
|
const Color(0x66666666),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final RadialGradient testGradient2 = const RadialGradient(
|
||||||
|
center: Alignment.center,
|
||||||
|
radius: 20.0,
|
||||||
|
colors: const <Color>[
|
||||||
|
const Color(0x44444444),
|
||||||
|
const Color(0x88888888),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient2, 0.0), testGradient1);
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient2, 1.0), testGradient2);
|
||||||
|
expect(Gradient.lerp(testGradient1, testGradient2, 0.5), testGradient2.scale(0.0));
|
||||||
|
});
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user