I am trying to simulate sunrise/sunset with a linear gradient. I want the gradient to rotate around a circle whose diameter is the width of the screen with the center point being the very bottom middle of the screen.
I found this this answer on a different thread with a similar question, but I am still left confused.
The following is my current attempt:
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
// Circle is intended to be screen width
// Radius then is half the width of the screen
double radius = width / 2;
// Center of the circle.
// Intended to be the very bottom center of the screen
double centerX = radius;
double centerY = height;
// Using x = r * sin(a) and y = r * cos(a) to get the coordinates of the start and end points
// The angle is elapsed percent of 360 degrees
double beginVectorX = radius * sin(360 * _percentOfDayElapsed);
double beginVectorY = radius * cos(360 * _percentOfDayElapsed);
// The end coordinates need to always be on the opposite end of the circle
// The angle is the same as the start coordinates but shifted 180 degrees
double endVectorX = radius * sin((360 * _percentOfDayElapsed) + 180);
double endVectorY = radius * cos((360 * _percentOfDayElapsed) + 180);
// The coordinates then need to be added to the center to get the points relative to the position of the circle
double beginX = centerX + beginVectorX;
double beginY = centerY + beginVectorY;
double endX = centerX + endVectorX;
double endY = centerY + endVectorY;
// The coordinates then need to be converted from absolute X, Y to relative alignment
// Relative alignment means: (-1, -1) is top left, (0, 0) is center, and (1, 1) is bottom right
// Conversion forumli: (2 * x - w) / w and (2 * y - h) / h
begin = Alignment(
(2 * beginX - width) / width, (2 * beginY - height) / height);
end = Alignment(
(2 * endX - width) / width, (2 * endY - height) / height)
The following is a quote from the answer that I used (p0 is the center of the circle, p1 and p2 are the two points on opposite ends, a is the rotation of p1, and the orange vector is the radius of the circle):
Basic trigonometry says that to get the x value of the orange vector (p0 to p1), we can do r * sin(a) and for its y, do r * cos(a). Hence to find p1, add the orange vector to p0. For p2, subtract the orange vector from p0. You can then use p1 and p2 to draw your gradient.
What I don't understand is what it means by adding and subtracting the vector from the center point. I believe I'm doing that here:
// The coordinates then need to be added to the center to get the points relative to the position of the circle
double beginX = centerX + beginVectorX;
double beginY = centerY + beginVectorY;
double endX = centerX + endVectorX;
double endY = centerY + endVectorY;
but I'm not really sure.
The problem is that while the gradient does rotate around the right spot, a full rotation is about 25 minutes instead of 24 hours.
Also, keep in mind that the origin of the screen is at the top left, and moving downward is an increase in Y and moving right is an increase in X. That is why I'm still adding the vector to the center for the point at the other end, even though the answer said to subtract.
I don't think _percentOfDayElapsed is affecting anything adversely, but just in case, it is defined as follows:
Timer.periodic(const Duration(milliseconds: 100), (timer) {
final now = DateTime.now();
setState(() {
_percentOfDayElapsed =
((now.hour * 3600) + (now.minute * 60) + now.second) / 86400;
});
});