mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 15:29:15 +01:00
anchor the hero darkening to the content so it scrolls with it
This commit is contained in:
@@ -80,6 +80,7 @@ import com.subtracks.ui.theme.ArtworkColors
|
|||||||
import com.subtracks.ui.theme.ArtworkTheme
|
import com.subtracks.ui.theme.ArtworkTheme
|
||||||
import com.subtracks.ui.theme.HeroGradient
|
import com.subtracks.ui.theme.HeroGradient
|
||||||
import com.subtracks.ui.theme.gradientColorAt
|
import com.subtracks.ui.theme.gradientColorAt
|
||||||
|
import com.subtracks.ui.theme.heroDarkenAt
|
||||||
import com.subtracks.ui.theme.rememberArtworkColors
|
import com.subtracks.ui.theme.rememberArtworkColors
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
@@ -166,7 +167,14 @@ fun AlbumDetailScreen(
|
|||||||
label = "gradientAlpha",
|
label = "gradientAlpha",
|
||||||
)
|
)
|
||||||
val barColor =
|
val barColor =
|
||||||
artwork?.gradientColorAt((scrollPx + barHeightPx / 2f) / gradientHeightPx) ?: Color.Black
|
artwork?.let {
|
||||||
|
val mid = scrollPx + barHeightPx / 2f
|
||||||
|
lerp(
|
||||||
|
it.gradientColorAt(mid / gradientHeightPx),
|
||||||
|
Color.Black,
|
||||||
|
heroDarkenAt(mid, with(density) { maxHeight.toPx() }),
|
||||||
|
)
|
||||||
|
} ?: Color.Black
|
||||||
|
|
||||||
HeroGradient(
|
HeroGradient(
|
||||||
colors = artwork,
|
colors = artwork,
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ private const val PERIOD_SCREENS = 2f
|
|||||||
private const val BLOB_ZONE = 0.62f
|
private const val BLOB_ZONE = 0.62f
|
||||||
private const val BLOB_COUNT = 4
|
private const val BLOB_COUNT = 4
|
||||||
private const val ACCENT_MAX_LUMINANCE = 0.34f
|
private const val ACCENT_MAX_LUMINANCE = 0.34f
|
||||||
private const val HERO_DARKEN_MAX = 0.85f
|
private const val HERO_DARKEN_MAX = 0.8f
|
||||||
private const val HERO_DARKEN_SCREENS = 1.5f
|
private const val DARKEN_START_SCREENS = 0.5f
|
||||||
private const val BASE_BOTTOM_DARKEN = 0.6f
|
private const val DARKEN_END_SCREENS = 1.5f
|
||||||
private const val POSITION_FADE_START = 0.55f
|
private const val DARKEN_KNEE = 0.2f
|
||||||
|
|
||||||
data class ArtworkColors(
|
data class ArtworkColors(
|
||||||
val scheme: ColorScheme,
|
val scheme: ColorScheme,
|
||||||
@@ -284,22 +284,39 @@ fun HeroGradient(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val progress = (scroll / (size.height * HERO_DARKEN_SCREENS)).coerceIn(0f, 1f)
|
val darkenStart = size.height * DARKEN_START_SCREENS - scroll
|
||||||
val bottomAlpha = BASE_BOTTOM_DARKEN + (HERO_DARKEN_MAX - BASE_BOTTOM_DARKEN) * progress
|
val darkenEnd = size.height * DARKEN_END_SCREENS - scroll
|
||||||
drawRect(
|
drawRect(
|
||||||
brush =
|
brush =
|
||||||
Brush.verticalGradient(
|
Brush.verticalGradient(
|
||||||
colorStops =
|
colorStops =
|
||||||
arrayOf(
|
arrayOf(
|
||||||
0f to Color.Transparent,
|
0f to Color.Transparent,
|
||||||
POSITION_FADE_START to Color.Transparent,
|
DARKEN_KNEE to Color.Black.copy(alpha = HERO_DARKEN_MAX * 0.5f),
|
||||||
1f to Color.Black.copy(alpha = bottomAlpha),
|
1f to Color.Black.copy(alpha = HERO_DARKEN_MAX),
|
||||||
),
|
),
|
||||||
|
startY = darkenStart,
|
||||||
|
endY = darkenEnd,
|
||||||
|
tileMode = TileMode.Clamp,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun heroDarkenAt(
|
||||||
|
contentY: Float,
|
||||||
|
screenHeightPx: Float,
|
||||||
|
): Float {
|
||||||
|
val start = screenHeightPx * DARKEN_START_SCREENS
|
||||||
|
val end = screenHeightPx * DARKEN_END_SCREENS
|
||||||
|
val fraction = ((contentY - start) / (end - start)).coerceIn(0f, 1f)
|
||||||
|
return if (fraction <= DARKEN_KNEE) {
|
||||||
|
HERO_DARKEN_MAX * 0.5f * (fraction / DARKEN_KNEE)
|
||||||
|
} else {
|
||||||
|
HERO_DARKEN_MAX * 0.5f + HERO_DARKEN_MAX * 0.5f * ((fraction - DARKEN_KNEE) / (1f - DARKEN_KNEE))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Color.toHsl(): Triple<Float, Float, Float> {
|
private fun Color.toHsl(): Triple<Float, Float, Float> {
|
||||||
val max = maxOf(red, green, blue)
|
val max = maxOf(red, green, blue)
|
||||||
val min = minOf(red, green, blue)
|
val min = minOf(red, green, blue)
|
||||||
|
|||||||
Reference in New Issue
Block a user