lerp LinearGradient (#9628)
* Implement * Don’t scale the fractional offsets since it’s easier to use * review notes * fix nit
This commit is contained in:
parent
66ed8de745
commit
3a0ce961ca
@ -637,7 +637,10 @@ class LinearGradient extends Gradient {
|
||||
this.colors,
|
||||
this.stops,
|
||||
this.tileMode: TileMode.clamp
|
||||
});
|
||||
}) : assert(begin != null),
|
||||
assert(end != null),
|
||||
assert(colors != null),
|
||||
assert(tileMode != null);
|
||||
|
||||
/// The offset from coordinate (0.0,0.0) at which stop 0.0 of the
|
||||
/// gradient is placed, in a coordinate space that maps the top left
|
||||
@ -679,6 +682,54 @@ class LinearGradient extends Gradient {
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a new [LinearGradient] with its properties scaled by the given factor.
|
||||
LinearGradient scale(double factor) {
|
||||
return new LinearGradient(
|
||||
begin: begin,
|
||||
end: end,
|
||||
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)).toList(),
|
||||
stops: stops,
|
||||
tileMode: tileMode,
|
||||
);
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two [LinearGradient]s.
|
||||
///
|
||||
/// If either gradient is null, this function linearly interpolates from a
|
||||
/// a gradient that matches the other gradient in begin, end, stops and
|
||||
/// tileMode and with the same colors but transparent.
|
||||
static LinearGradient lerp(LinearGradient a, LinearGradient 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);
|
||||
// Interpolation is only possible when the lengths of colors and stops are
|
||||
// the same or stops is null for one.
|
||||
// TODO(xster): lerp unsimilar LinearGradients in the future by scaling
|
||||
// lists of LinearGradients.
|
||||
assert(a.colors.length == b.colors.length);
|
||||
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++)
|
||||
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++)
|
||||
interpolatedStops.add(ui.lerpDouble(a.stops[i], b.stops[i], t));
|
||||
} else {
|
||||
interpolatedStops = a.stops ?? b.stops;
|
||||
}
|
||||
return new LinearGradient(
|
||||
begin: FractionalOffset.lerp(a.begin, b.begin, t),
|
||||
end: FractionalOffset.lerp(a.end, b.end, t),
|
||||
colors: interpolatedColors,
|
||||
stops: interpolatedStops,
|
||||
tileMode: t < 0.5 ? a.tileMode : b.tileMode,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
if (identical(this, other))
|
||||
|
@ -6,7 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
void main() {
|
||||
test("BorderSide control test", () {
|
||||
test('BorderSide control test', () {
|
||||
final BorderSide side1 = const BorderSide();
|
||||
final BorderSide side2 = side1.copyWith(
|
||||
color: const Color(0xFF00FFFF),
|
||||
@ -39,7 +39,7 @@ void main() {
|
||||
expect(interpolated.color, equals(side2.color.withOpacity(0.2)));
|
||||
});
|
||||
|
||||
test("Border control test", () {
|
||||
test('Border control test', () {
|
||||
final Border border1 = new Border.all(width: 4.0);
|
||||
final Border border2 = Border.lerp(null, border1, 0.25);
|
||||
final Border border3 = Border.lerp(border1, null, 0.25);
|
||||
@ -54,7 +54,7 @@ void main() {
|
||||
expect(border4.left.width, equals(2.0));
|
||||
});
|
||||
|
||||
test("BoxShadow control test", () {
|
||||
test('BoxShadow control test', () {
|
||||
final BoxShadow shadow1 = const BoxShadow(blurRadius: 4.0);
|
||||
final BoxShadow shadow2 = BoxShadow.lerp(null, shadow1, 0.25);
|
||||
final BoxShadow shadow3 = BoxShadow.lerp(shadow1, null, 0.25);
|
||||
@ -76,4 +76,58 @@ void main() {
|
||||
<BoxShadow>[shadow2], <BoxShadow>[shadow3, shadow1], 0.5);
|
||||
expect(shadowList, equals(<BoxShadow>[shadow4, shadow1.scale(0.5)]));
|
||||
});
|
||||
|
||||
test('LinearGradient scale test', () {
|
||||
final LinearGradient testGradient = const LinearGradient(
|
||||
begin: FractionalOffset.bottomRight,
|
||||
end: const FractionalOffset(0.7, 1.0),
|
||||
colors: const <Color>[
|
||||
const Color(0x00FFFFFF),
|
||||
const Color(0x11777777),
|
||||
const Color(0x44444444),
|
||||
],
|
||||
);
|
||||
final LinearGradient actual = LinearGradient.lerp(null, testGradient, 0.25);
|
||||
|
||||
expect(actual, const LinearGradient(
|
||||
begin: FractionalOffset.bottomRight,
|
||||
end: const FractionalOffset(0.7, 1.0),
|
||||
colors: const <Color>[
|
||||
const Color(0x00FFFFFF),
|
||||
const Color(0x04777777),
|
||||
const Color(0x11444444),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('LinearGradient lerp test', () {
|
||||
final LinearGradient testGradient1 = const LinearGradient(
|
||||
begin: FractionalOffset.topLeft,
|
||||
end: FractionalOffset.bottomLeft,
|
||||
colors: const <Color>[
|
||||
const Color(0x33333333),
|
||||
const Color(0x66666666),
|
||||
],
|
||||
);
|
||||
|
||||
final LinearGradient testGradient2 = const LinearGradient(
|
||||
begin: FractionalOffset.topRight,
|
||||
end: FractionalOffset.topLeft,
|
||||
colors: const <Color>[
|
||||
const Color(0x44444444),
|
||||
const Color(0x88888888),
|
||||
],
|
||||
);
|
||||
final LinearGradient actual =
|
||||
LinearGradient.lerp(testGradient1, testGradient2, 0.5);
|
||||
|
||||
expect(actual, const LinearGradient(
|
||||
begin: const FractionalOffset(0.5, 0.0),
|
||||
end: const FractionalOffset(0.0, 0.5),
|
||||
colors: const <Color>[
|
||||
const Color(0x3B3B3B3B),
|
||||
const Color(0x77777777),
|
||||
],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user