Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gradient transform #42484

Merged
merged 20 commits into from Oct 11, 2019
Merged

Gradient transform #42484

merged 20 commits into from Oct 11, 2019

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Oct 11, 2019

Description

Exposes the transform parameter for gradients into the framework via a GradientTransform class, which is akin to Alignment or EdgeInsets in that it resolves an actual Matrix4 by means of a Rect (and potentially a TextDirection). This enables more easily creating rotated gradient effects without having to rotate the entire canvas.

Fixes #23648

Related Issues

#23648

Tests

I added the following tests:

Golden tests for transformed gradients.

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (Please read Handling breaking changes). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

@fluttergithubbot fluttergithubbot added the framework flutter/packages/flutter repository. See also f: labels. label Oct 11, 2019
dnfield added a commit to flutter/goldens that referenced this pull request Oct 11, 2019
Comment on lines 144 to 153
/// // Calculate the point to rotate about.
/// final double sinRadians = math.sin(radians);
/// final double oneMinusCosRadians = 1 - math.cos(radians);
/// final Offset center = rect.center;
/// final double originX = sinRadians * center.dy + oneMinusCosRadians * center.dx;
/// final double originY = -sinRadians * center.dx + oneMinusCosRadians * center.dy;
///
/// final Matrix4 transform = Matrix4.identity()
/// ..translate(originX, originY)
/// ..rotateZ(radians);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect having amethod like this in the framework might be helpful to people, but I'm not sure where it would go. MatrixUtils?

@goderbauer wdyt?

@Hixie
Copy link
Contributor

Hixie commented Oct 11, 2019

Would it make more sense for the matrix to be a property rather than something you pass to createShader? The shader is created pretty low-down, most people don't use that API.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 11, 2019

The thing is, you're generally going to need to know the Rect that's being used for createShader to make sense of what to do with your matrix. And the people requesting this in the linked bug were already using createShader to apply this to a Paint object's shader property in things like a CustomPaint anyway.

It would be nice but I'm not sure how we'd really abstract the rect away properly.

@dnfield
Copy link
Contributor Author

dnfield commented Oct 11, 2019

We could maybe give it a callback where you're given a rect and you give back a transform, like:

typdef MatrixBuilder = Matrix4 Function(Rect rect);

And then createShader would call that and use the transform created by that to transform the shader. That would make this more useable in something like a BoxDecoration. WDYT?

@Hixie
Copy link
Contributor

Hixie commented Oct 11, 2019

We could also take a new kind of class that represents a matrix transform. That class would have a method on it that takes a rect to do the actual transform computation. This is analogous to what we do wiht Alignment or EdgeInsets (both of which need the actual Rect to do their actual work, but don't have it available when you specify them).

dnfield added a commit to flutter/goldens that referenced this pull request Oct 11, 2019
@dnfield dnfield requested a review from Hixie October 11, 2019 03:45
@dnfield
Copy link
Contributor Author

dnfield commented Oct 11, 2019

I've added a GradientTransform and a GradientRotation class.

We could trivially implement things like GradientTranslate and GradientSkew and the like - rotation is probably the hardest of the bunch though and it's the only one being asked for right now.

///
/// For example, a [SweepGradient] normally starts its gradation at 3 o'clock
/// and draws clockwise. To have the sweep appear to start at 6 o'clock, supply
/// a [GradientRotation] of `0.785398` radians (i.e. `45` degrees).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trivial nit: I think our style is to not use backticks for literals.

/// a [GradientRotation] of `0.785398` radians (i.e. `45` degrees).
@immutable
abstract class GradientTransform {
/// A const constructor that allows subclasses to be const.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a boilerplate paragraph we use for this kind of thing.

/// colors: colors,
/// transform: GradientRotation(0.785398),
/// );
/// ```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use the sample code logic for this

/// ```
@immutable
class GradientRotation extends GradientTransform {
/// Constructs a `GradientRotation` for the specified angle.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use [] for identifiers

/// The angle is in radians in the clockwise direction.
const GradientRotation(this.radians);

/// The angle of rotation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs more detail, e.g. direction of rotation (clockwise, counter-clockwise), the units (though it's pretty obvious from the name).

///
/// The [transform] argument can be applied to transform _only_ the gradient,
/// without rotating the canvas itself or other geometry on the canvas. For
/// example, a `GradientRotation(0.785398)` will result in a [SweepGradient]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and elsewhere, rather than 0.785398 we should say pi/4

@Hixie
Copy link
Contributor

Hixie commented Oct 11, 2019

This looks great!
LGTM

dnfield added a commit to flutter/goldens that referenced this pull request Oct 11, 2019
@dnfield
Copy link
Contributor Author

dnfield commented Oct 11, 2019

In case it's not obvious - I've rev'd goldens a few times in this because I've made very minor changes to the tests that are resulting in miniscule pixel differences.

@dnfield dnfield added the will affect goldens Changes to golden files label Oct 11, 2019
@dnfield dnfield merged commit de499c2 into flutter:master Oct 11, 2019
@dnfield dnfield deleted the gradient_transform branch October 11, 2019 20:40
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
framework flutter/packages/flutter repository. See also f: labels. will affect goldens Changes to golden files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SweepGradient startAngle doesn't work as expected.
4 participants