在Compose中无限并可逆地动画线性渐变(刷子)。

huangapple go评论102阅读模式
英文:

Animate Linear Gradient (Brush) infinitely and reversely in Compose

问题

初始状态如下 (animatedOffset = 0f)

在Compose中无限并可逆地动画线性渐变(刷子)。

1f 时,我想要获取反向渐变:

在Compose中无限并可逆地动画线性渐变(刷子)。

当前代码:

  1. val transition = rememberInfiniteTransition(label = "NavIconGradientAnim")
  2. val animatedOffset by transition.animateFloat(
  3. initialValue = 0f, targetValue = 1f,
  4. label = "NavIconGradientAnimOffset",
  5. animationSpec = infiniteRepeatable(
  6. animation = tween(1500, easing = LinearEasing),
  7. repeatMode = RepeatMode.Reverse
  8. )
  9. )
  10. Image(
  11. painterResource(id = item.icon),
  12. contentDescription = null,
  13. modifier = Modifier.drawWithCache {
  14. onDrawWithContent {
  15. with(drawContext.canvas.nativeCanvas) {
  16. val angle = 45f
  17. val endX = drawContext.size.width
  18. val endY = (endX * kotlin.math.tan(Math.toRadians(angle.toDouble()))).toFloat()
  19. val checkPoint = saveLayer(null, null)
  20. drawContent()
  21. val gradient = Brush.linearGradient(
  22. colors = listOf(Color.Blue, Color.Yellow),
  23. start = Offset(animatedOffset * endX, animatedOffset * endY),
  24. end = Offset(endX, endX)
  25. )
  26. drawRect(
  27. brush = gradient,
  28. blendMode = BlendMode.SrcIn
  29. )
  30. restoreToCount(checkPoint)
  31. }
  32. }
  33. }
  34. )

我尝试设置

end = Offset(endX - animatedOffset * endX, endY - animatedOffset * endY),

但它看起来不好(GIF 预览):

在Compose中无限并可逆地动画线性渐变(刷子)。

颜色变化突然。

英文:

Initial State looks like this (animatedOffset = 0f)

在Compose中无限并可逆地动画线性渐变(刷子)。

at 1f I want to get the reversed gradient:

在Compose中无限并可逆地动画线性渐变(刷子)。

Current code:

  1. val transition = rememberInfiniteTransition(label = "NavIconGradientAnim")
  2. val animatedOffset by transition.animateFloat(
  3. initialValue = 0f, targetValue = 1f,
  4. label = "NavIconGradientAnimOffset",
  5. animationSpec = infiniteRepeatable(
  6. animation = tween(1500, easing = LinearEasing),
  7. repeatMode = RepeatMode.Reverse
  8. )
  9. )
  10. Image(
  11. painterResource(id = item.icon),
  12. contentDescription = null,
  13. modifier = Modifier.drawWithCache {
  14. onDrawWithContent {
  15. with(drawContext.canvas.nativeCanvas) {
  16. val angle = 45f
  17. val endX = drawContext.size.width
  18. val endY = (endX * kotlin.math.tan(Math.toRadians(angle.toDouble()))).toFloat()
  19. val checkPoint = saveLayer(null, null)
  20. drawContent()
  21. val gradient = Brush.linearGradient(
  22. colors = listOf(Color.Blue, Color.Yellow),
  23. start = Offset(animatedOffset * endX, animatedOffset * endY),
  24. end = Offset(endX, endX)
  25. )
  26. drawRect(
  27. brush = gradient,
  28. blendMode = BlendMode.SrcIn
  29. )
  30. restoreToCount(checkPoint)
  31. }
  32. }
  33. }
  34. )

I tried to set

end = Offset(endX - animatedOffset * endX, endY - animatedOffset * endY),

but it doesn't look good (GIF preview):

在Compose中无限并可逆地动画线性渐变(刷子)。

it changes color abruptly

答案1

得分: 1

以下是翻译好的部分:

有几种方法可以做到这一点,你不必计算切线。

一种方法是

  1. val limit = 1.5f
  2. val transition = rememberInfiniteTransition(label = "shimmer")
  3. val progressAnimated by transition.animateFloat(
  4. initialValue = -limit,
  5. targetValue = limit,
  6. animationSpec = infiniteRepeatable(
  7. animation = tween(1500, easing = LinearEasing),
  8. repeatMode = RepeatMode.Reverse
  9. ), label = "shimmer"
  10. )

并设置画笔(brush):

  1. val width = size.width
  2. val height = size.height
  3. val offset = width * progress
  4. val gradientWidth = width
  5. val brush = Brush.linearGradient(
  6. colors = gradientColors,
  7. start = Offset(offset, 0f),
  8. end = Offset(offset + gradientWidth, height)
  9. )

结果

在Compose中无限并可逆地动画线性渐变(刷子)。

演示

  1. @Preview
  2. @Composable
  3. private fun SingleGradientTest() {
  4. Column(
  5. Modifier.padding(20.dp)
  6. ) {
  7. val painterStar = painterResource(id = R.drawable.star_foreground)
  8. val limit = 1.5f
  9. var progress by remember {
  10. mutableStateOf(-limit)
  11. }
  12. val transition = rememberInfiniteTransition(label = "shimmer")
  13. val progressAnimated by transition.animateFloat(
  14. initialValue = -limit,
  15. targetValue = limit,
  16. animationSpec = infiniteRepeatable(
  17. animation = tween(1500, easing = LinearEasing),
  18. repeatMode = RepeatMode.Reverse
  19. ), label = "shimmer"
  20. )
  21. Box(
  22. modifier = Modifier
  23. .fillMaxWidth()
  24. .aspectRatio(1f)
  25. .drawWithCache {
  26. val width = size.width
  27. val height = size.height
  28. val offset = width * progress
  29. val gradientWidth = width
  30. val brush = Brush.linearGradient(
  31. colors = gradientColors,
  32. start = Offset(offset, 0f),
  33. end = Offset(offset + gradientWidth, height)
  34. )
  35. onDrawBehind {
  36. drawRect(
  37. brush = brush,
  38. blendMode = BlendMode.SrcIn
  39. )
  40. }
  41. }
  42. )
  43. Box(
  44. modifier = Modifier
  45. .size(100.dp)
  46. .graphicsLayer {
  47. compositingStrategy = CompositingStrategy.Offscreen
  48. }
  49. .drawWithCache {
  50. val width = size.width
  51. val height = size.height
  52. val offset = width * progress
  53. val gradientWidth = width
  54. val brush = Brush.linearGradient(
  55. colors = gradientColors,
  56. start = Offset(offset, 0f),
  57. end = Offset(offset + gradientWidth, height)
  58. )
  59. onDrawBehind {
  60. // Destination
  61. with(painterStar) {
  62. draw(
  63. size = Size(width, width)
  64. )
  65. }
  66. // Source
  67. drawRect(
  68. brush = brush,
  69. blendMode = BlendMode.SrcIn
  70. )
  71. }
  72. }
  73. )
  74. Text("Progress: $progress")
  75. Slider(
  76. value = progress,
  77. onValueChange = { progress = it },
  78. valueRange = -limit..limit
  79. )
  80. Text(text = "Animated progress: $progressAnimated")
  81. Box(
  82. modifier = Modifier
  83. .size(100.dp)
  84. .graphicsLayer {
  85. compositingStrategy = CompositingStrategy.Offscreen
  86. }
  87. .drawWithCache {
  88. val width = size.width
  89. val height = size.height
  90. val offset = width * progressAnimated
  91. val gradientWidth = width
  92. val brush = Brush.linearGradient(
  93. colors = gradientColors,
  94. start = Offset(offset, 0f),
  95. end = Offset(offset + gradientWidth, height)
  96. )
  97. onDrawBehind {
  98. // Destination
  99. with(painterStar) {
  100. draw(
  101. size = Size(width, width)
  102. )
  103. }
  104. // Source
  105. drawRect(
  106. brush = brush,
  107. blendMode = BlendMode.SrcIn
  108. )
  109. }
  110. }
  111. )
  112. }
  113. }
英文:

There are several ways to do it and you don't have to calculate tangent.

One way of doing it is

  1. val limit = 1.5f
  2. val transition = rememberInfiniteTransition(label = "shimmer")
  3. val progressAnimated by transition.animateFloat(
  4. initialValue = -limit,
  5. targetValue = limit,
  6. animationSpec = infiniteRepeatable(
  7. animation = tween(1500, easing = LinearEasing),
  8. repeatMode = RepeatMode.Reverse
  9. ), label = "shimmer"
  10. )

And set brush with

val width = size.width
val height = size.height

  1. val offset = width * progress
  2. val gradientWidth = width
  3. val brush = Brush.linearGradient(
  4. colors = gradientColors,
  5. start = Offset(offset, 0f),
  6. end = Offset(offset + gradientWidth, height)
  7. )

Result

在Compose中无限并可逆地动画线性渐变(刷子)。

Demo

  1. @Preview
  2. @Composable
  3. private fun SingleGradientTest() {
  4. Column(
  5. Modifier.padding(20.dp)
  6. ) {
  7. val painterStar = painterResource(id = R.drawable.star_foreground)
  8. val limit = 1.5f
  9. var progress by remember {
  10. mutableStateOf(-limit)
  11. }
  12. val transition = rememberInfiniteTransition(label = "shimmer")
  13. val progressAnimated by transition.animateFloat(
  14. initialValue = -limit,
  15. targetValue = limit,
  16. animationSpec = infiniteRepeatable(
  17. animation = tween(1500, easing = LinearEasing),
  18. repeatMode = RepeatMode.Reverse
  19. ), label = "shimmer"
  20. )
  21. Box(
  22. modifier = Modifier
  23. .fillMaxWidth()
  24. .aspectRatio(1f)
  25. .drawWithCache {
  26. val width = size.width
  27. val height = size.height
  28. val offset = width * progress
  29. val gradientWidth = width
  30. val brush = Brush.linearGradient(
  31. colors = gradientColors,
  32. start = Offset(offset, 0f),
  33. end = Offset(offset + gradientWidth, height)
  34. )
  35. onDrawBehind {
  36. drawRect(
  37. brush = brush,
  38. blendMode = BlendMode.SrcIn
  39. )
  40. }
  41. }
  42. )
  43. Box(
  44. modifier = Modifier
  45. .size(100.dp)
  46. .graphicsLayer {
  47. compositingStrategy = CompositingStrategy.Offscreen
  48. }
  49. .drawWithCache {
  50. val width = size.width
  51. val height = size.height
  52. val offset = width * progress
  53. val gradientWidth = width
  54. val brush = Brush.linearGradient(
  55. colors = gradientColors,
  56. start = Offset(offset, 0f),
  57. end = Offset(offset + gradientWidth, height)
  58. )
  59. onDrawBehind {
  60. // Destination
  61. with(painterStar) {
  62. draw(
  63. size = Size(width, width)
  64. )
  65. }
  66. // Source
  67. drawRect(
  68. brush = brush,
  69. blendMode = BlendMode.SrcIn
  70. )
  71. }
  72. }
  73. )
  74. Text("Progress: $progress")
  75. Slider(
  76. value = progress,
  77. onValueChange = { progress = it },
  78. valueRange = -limit..limit
  79. )
  80. Text(text = "Animated progress: $progressAnimated")
  81. Box(
  82. modifier = Modifier
  83. .size(100.dp)
  84. .graphicsLayer {
  85. compositingStrategy = CompositingStrategy.Offscreen
  86. }
  87. .drawWithCache {
  88. val width = size.width
  89. val height = size.height
  90. val offset = width * progressAnimated
  91. val gradientWidth = width
  92. val brush = Brush.linearGradient(
  93. colors = gradientColors,
  94. start = Offset(offset, 0f),
  95. end = Offset(offset + gradientWidth, height)
  96. )
  97. onDrawBehind {
  98. // Destination
  99. with(painterStar) {
  100. draw(
  101. size = Size(width, width)
  102. )
  103. }
  104. // Source
  105. drawRect(
  106. brush = brush,
  107. blendMode = BlendMode.SrcIn
  108. )
  109. }
  110. }
  111. )
  112. }
  113. }

huangapple
  • 本文由 发表于 2023年7月27日 19:08:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76779131.html
  • android
  • android-animation
  • android-jetpack-compose
  • android-jetpack-compose-animation
  • jetpack-compose-animation
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定