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.colors,
|
||||||
this.stops,
|
this.stops,
|
||||||
this.tileMode: TileMode.clamp
|
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
|
/// 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
|
/// 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
|
@override
|
||||||
bool operator ==(dynamic other) {
|
bool operator ==(dynamic other) {
|
||||||
if (identical(this, other))
|
if (identical(this, other))
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test("BorderSide control test", () {
|
test('BorderSide control test', () {
|
||||||
final BorderSide side1 = const BorderSide();
|
final BorderSide side1 = const BorderSide();
|
||||||
final BorderSide side2 = side1.copyWith(
|
final BorderSide side2 = side1.copyWith(
|
||||||
color: const Color(0xFF00FFFF),
|
color: const Color(0xFF00FFFF),
|
||||||
@ -39,7 +39,7 @@ void main() {
|
|||||||
expect(interpolated.color, equals(side2.color.withOpacity(0.2)));
|
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 border1 = new Border.all(width: 4.0);
|
||||||
final Border border2 = Border.lerp(null, border1, 0.25);
|
final Border border2 = Border.lerp(null, border1, 0.25);
|
||||||
final Border border3 = Border.lerp(border1, null, 0.25);
|
final Border border3 = Border.lerp(border1, null, 0.25);
|
||||||
@ -54,7 +54,7 @@ void main() {
|
|||||||
expect(border4.left.width, equals(2.0));
|
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 shadow1 = const BoxShadow(blurRadius: 4.0);
|
||||||
final BoxShadow shadow2 = BoxShadow.lerp(null, shadow1, 0.25);
|
final BoxShadow shadow2 = BoxShadow.lerp(null, shadow1, 0.25);
|
||||||
final BoxShadow shadow3 = BoxShadow.lerp(shadow1, null, 0.25);
|
final BoxShadow shadow3 = BoxShadow.lerp(shadow1, null, 0.25);
|
||||||
@ -76,4 +76,58 @@ void main() {
|
|||||||
<BoxShadow>[shadow2], <BoxShadow>[shadow3, shadow1], 0.5);
|
<BoxShadow>[shadow2], <BoxShadow>[shadow3, shadow1], 0.5);
|
||||||
expect(shadowList, equals(<BoxShadow>[shadow4, shadow1.scale(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