I am trying to animate circle drawing using drawCircle on Canvas as follows:
drawCircle(
color = Color.Black,
radius = 200f * animatableCircle.value,
center = Offset(size.width / 4, size.height / 4),
style = Stroke(2f)
)
It doesn't look like circle is being drawn, instead the circle starts to scale from the centre. Is it possible to achieve circle drawing effect as in along the radius similar to CircularProgressIndicator as shown?
Just to complete the code posted by #Varsha Kulkarni: (+1)
val radius = 200f
val animateFloat = remember { Animatable(0f) }
LaunchedEffect(animateFloat) {
animateFloat.animateTo(
targetValue = 1f,
animationSpec = tween(durationMillis = 3000, easing = LinearEasing))
}
Canvas(modifier = Modifier.fillMaxSize()){
drawArc(
color = Color.Black,
startAngle = 0f,
sweepAngle = 360f * animateFloat.value,
useCenter = false,
topLeft = Offset(size.width / 4, size.height / 4),
size = Size(radius * 2 ,
radius * 2),
style = Stroke(2.0f))
}
Using drawArc as follows,
drawArc(
color = Color.Black,
startAngle = 0f,
sweepAngle = 360f * animatableCircle.value,
useCenter = false,
topLeft = Offset(size.width / 4, size.height / 4),
size = Size(CIRCLE_RADIUS * 2 ,
CIRCLE_RADIUS * 2),
style = Stroke(2.0f))
Related
I am using Canvas Api to draw something. I want to draw line with rounded corner. Line is draw without any problem. But I cannot figure out which attribute for corner radius.
val boxSize = 30.dp
Box(modifier = Modifier
.background(Color.LightGray)
.height(height = boxSize)
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
) {
val canvasWidth = size.width
drawLine(
start = Offset(x = 0f, y = (boxSize / 2).toPx()),
end = Offset(x = canvasWidth, y = (boxSize / 2).toPx()),
color = Color.Black,
strokeWidth = 8.dp.toPx()
)
}
}
My view is simple without corner radius.
I want my Black line to be corner for each side with specific radius.
You need to add the cap argument to drawLine and set it to StrokeCap.Round.
drawLine(
start = Offset(x = 0f, y = (boxSize / 2).toPx()),
end = Offset(x = canvasWidth, y = (boxSize / 2).toPx()),
color = Color.Black,
strokeWidth = 8.dp.toPx(),
cap = StrokeCap.Round, //add this line for rounded edges
)
I have the following two overlaying 360 degrees arc (essentially two circles) clipped by an arc shape. Unlike drawArc, addArc does not take into style = ... which can be used to define cap = StrokeCap.Round. The current clip looks as expected, an arc clipped with hard edges. Is there a way to round out the corners??
I tried using blendMode, but that does not work as expected since the color of the layers could be diffrent opacity, which blend mode takes in consideration when blending.
Canvas(modifier = Modifier.fillMaxSize()) {
val path = Path().apply {
this.addArc(
oval = Rect(
topLeft = Offset(0F, 0F),
bottomRight = Offset(size.width, size.height)
),
startAngleDegrees = 0F,
sweepAngleDegrees = 240F
)
}
clipPath(path = path) {
// following two drawArc could be replaced w/ drawCircle
drawArc(
color = Color.Magenta.copy(alpha = 0.2F),
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(strokeWidthPx2, cap = StrokeCap.Round),
size = Size(size2, size2),
topLeft = Offset(offset2, offset2)
)
drawArc(
color = Color.Cyan,
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(strokeWidthPx, cap = StrokeCap.Round),
size = Size(size1, size1),
topLeft = Offset(offset, offset)
)
}
}
I have a custom canvas component. I want to test canvas UI objects like rect, line, text, etc. How should I test this sample UI?
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(canvasHeight.dp)
.pointerInput(Unit) {
detectTapGestures { offset ->
touchPosition.value = offset
}
}
)
{
drawArc(
color = Color(0xFFf04231),
startAngle = -90f,
sweepAngle = 180f,
useCenter = true,
size = Size(size.width * .50f, size.height * .50f),
topLeft = Offset(size.width * .25f, 0f)
)
drawPath(path = path, color = Color.White.copy(alpha = .90f))
drawCircle(
brush = Brush.verticalGradient(sunColor),
radius = width.times(.17f),
center = Offset(width.times(.35f), height.times(.35f))
)
}
When I use BlendMode.DstOut, it's supposed to show transparent source shape but it's black.
Supposed result:
Real result:
#Composable
fun BlendMode() {
Box(modifier = Modifier.fillMaxSize().background(White100))
Canvas(modifier = Modifier.size(300.dp)) {
val radius = size.width / 3
drawCircle(
color = Color.Red,
radius = radius,
center = Offset(radius, radius)
)
drawRect(
color = Color.Blue,
topLeft = Offset(radius, radius),
size = Size(radius * 2, radius * 2),
blendMode = BlendMode.DstOut
)
}
}
The blendMode will not allow you to achieve the desired result. You can do this by using clipRect:
clipRect(
top = radius,
left = radius,
right = radius * 3,
bottom = radius * 3,
clipOp = ClipOp.Difference
) {
drawCircle(
color = Color.Red,
radius = radius,
center = Offset(radius, radius)
)
}
I'm not sure how can I do the calculation in order to center this arc on the canvas? Can someone point me in the proper direction?
Canvas(modifier = Modifier
.background(Color.LightGray)
.fillMaxWidth()
.height(300.dp)
) {
drawArc(
color = Color.Blue,
startAngle = 30f,
sweepAngle = 300f,
useCenter = false,
style = Stroke(width = 50f, cap = StrokeCap.Round),
size = size/2.25F
)
}
Use the topLeft parameter in the drawArc method.
Something like:
val sizeArc = size/2.25F
drawArc(
color = Color.Blue,
startAngle = 30f,
sweepAngle = 300f,
topLeft = Offset((size.width - sizeArc.width)/2f,(size.height - sizeArc.height)/2f),
useCenter = false,
style = Stroke(width = 50f, cap = StrokeCap.Round),
size = sizeArc
)
#Composable
fun CustomArc() {
Canvas(modifier = Modifier.fillMaxSize()) {
val arcRadius = 200f
val canvasWidth = size.width
val canvasHeight = size.height
drawArc(
color = Color.Red,
startAngle = -90f, //start angle is always in clockwise direction
sweepAngle = 270f, // angle formed between the start angle
useCenter = false,
size = Size(arcRadius, arcRadius),
topLeft = Offset(
(canvasWidth / 2) - (arcRadius / 2),
canvasHeight / 2 - (arcRadius / 2)
),
style = Stroke(width = 10f, cap = StrokeCap.Round)
)
}
}