Skip to content

Instantly share code, notes, and snippets.

@DonizeteVida
Created October 12, 2023 23:38
Show Gist options
  • Select an option

  • Save DonizeteVida/decbdab9233f1c99d051129530c486a9 to your computer and use it in GitHub Desktop.

Select an option

Save DonizeteVida/decbdab9233f1c99d051129530c486a9 to your computer and use it in GitHub Desktop.
VynilDisk
internal const val CENTER_CUT_PERCENTAGE = 0.02F
internal const val IMAGE_RADIUS_PERCENTAGE = 0.4F
@Composable
fun CenterRotatable(
content: @Composable () -> Unit,
) {
var angle by remember { mutableStateOf(0F) }
var windowCenterPosition by remember { mutableStateOf(Offset.Zero) }
Box(
Modifier
.pointerInput(Unit) {
detectDragGestures { change, _ ->
val diff1 = change.position - windowCenterPosition
val diff2 = change.previousPosition - windowCenterPosition
val atan1 = atan2(diff1.y, diff1.x)
val atan2 = atan2(diff2.y, diff2.x)
val atan = atan1 - atan2
angle += Math
.toDegrees(atan.toDouble())
.toFloat()
}
}
.rotate(angle)
.onGloballyPositioned {
windowCenterPosition = it
.boundsInWindow()
.run {
Offset(right / 2F, bottom / 2F)
}
}
) {
content()
}
}
@Composable
fun VinylDisk(
modifier: Modifier,
painter: Painter,
diskColor: Color = Color.Black,
lightColor: Color = Color(0x34FFFFFF),
needleColors: List<Color> = listOf(
Color(0x99444444),
Color(0x22999999),
Color(0x99444444)
)
) {
Canvas(
modifier = modifier
) {
Path().apply {
addOval(Rect(center, size.minDimension * CENTER_CUT_PERCENTAGE)) //inner hole cut
drawContext.transform.clipPath(this, ClipOp.Difference)
addOval(Rect(center, size.minDimension * .5F)) //outer rounded border cut
drawContext.transform.clipPath(this)
}
drawRect(diskColor) //disk color
//some kinda of lighting into disk
val paint = Paint().apply {
color = lightColor
asFrameworkPaint().apply {
maskFilter = (BlurMaskFilter(100F, BlurMaskFilter.Blur.NORMAL))
}
}
drawIntoCanvas {
for (i in 1..4) {
it.drawArc(
Rect(0F, 0F, size.minDimension, size.minDimension),
(i / 4F) * 360,
30F,
true,
paint
)
}
}
// draw needle circular lines
for (i in 1..9) {
// rotate to avoid gradient visual pattern
rotate((i / 4F) * 360) {
drawCircle(
Brush.sweepGradient(needleColors),
size.minDimension * .5F * (i / 10F),
style = Stroke(1F)
)
}
}
// draw center image and fix its offset position by
// translating it when drawing
val imageRadius = size.minDimension * IMAGE_RADIUS_PERCENTAGE * .5F
Path().apply {
addOval(Rect(center, imageRadius))
clipPath(this) {
translate(
left = size.minDimension / 2F - imageRadius,
top = size.minDimension / 2F - imageRadius
) {
with(painter) {
draw(size * IMAGE_RADIUS_PERCENTAGE)
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment