Skip to content

Instantly share code, notes, and snippets.

@alexjlockwood
Created April 8, 2019 05:59
Show Gist options
  • Save alexjlockwood/2ea19f7c02804939979b1fc8b66c997c to your computer and use it in GitHub Desktop.
Save alexjlockwood/2ea19f7c02804939979b1fc8b66c997c to your computer and use it in GitHub Desktop.
Inspired by @beesandbombs (twitter.com/beesandbombs)
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
private const val PERIOD = 2500
private const val PI = Math.PI.toFloat()
private const val HALF_PI = PI / 2
class CircleSquareView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val circleRadius: Float
get() = Math.min(width, height).toFloat() / 4f / sqrt(2f)
private val circlePadding: Float
get() = circleRadius / 16f
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save()
canvas.translate(width / 2f, height / 2f)
val t = (System.currentTimeMillis() % PERIOD) / PERIOD.toFloat()
if (t <= 0.5) {
val tt = map(t, 0f, 0.5f, 0f, 1f)
val rotation = 90f * ease(tt, 3f)
canvas.save()
canvas.rotate(rotation)
canvas.drawCircles(270f, -360f * ease(tt, 3f))
canvas.restore()
} else {
val tt = map(t, 0.5f, 1f, 0f, 1f)
val rotation = -90f * ease(tt, 3f)
canvas.save()
canvas.rotate(rotation)
canvas.drawCircles(360f, 0f)
canvas.restore()
canvas.save()
canvas.rotate(-rotation)
paint.color = Color.WHITE
canvas.drawRect(-circleRadius, -circleRadius, circleRadius, circleRadius, paint)
canvas.restore()
}
canvas.restore()
postInvalidateOnAnimation()
}
private fun Canvas.drawCircles(sweepAngle: Float, rotation: Float) {
for (i in 0 until 4) {
val r = circleRadius * sqrt(2f)
val theta = (HALF_PI + PI * i) / 2f
val tx = r * cos(theta)
val ty = r * sin(theta)
save()
translate(-tx, -ty)
rotate(rotation)
paint.color = Color.BLACK
drawArc(
-circleRadius + circlePadding,
-circleRadius + circlePadding,
circleRadius - circlePadding,
circleRadius - circlePadding,
90f * (i + 1),
sweepAngle,
true,
paint
)
restore()
}
}
}
private fun map(value: Float, start1: Float, stop1: Float, start2: Float, stop2: Float): Float {
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1))
}
private fun ease(p: Float, g: Float): Float {
return if (p < 0.5f) {
0.5f * Math.pow(2.0 * p, g.toDouble()).toFloat()
} else {
1f - 0.5f * Math.pow(2.0 * (1f - p), g.toDouble()).toFloat()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment