I’ve a Rectangle()
SwiftUI view. I’m attempting to animate the fill inside it primarily based on a numeric worth. For instance the peak of the rectangle can be totalHeight
* ratio
. Right here is the code:
struct SquareOptionView: View {
let title: String
@Binding var voteRatio: Double
let shade: Coloration
let tapAction: ()->()
var physique: some View {
VStack(spacing: 10.0){
Textual content(title)
Textual content(
"(voteRatio * 100, specifier: "%.2f")%"
)
}
.padding(25.0)
.body(maxWidth: .infinity, alignment: .backside)
.background{
shade
.containerRelativeFrame(.vertical, alignment: .backside) { size, _ in
return size * voteRatio
}
.animation(.bouncy, worth: voteRatio)
.body(alignment: .backside)
}
.onTapGesture {
tapAction()
}
}
}
It really works effectively however the animation finally ends up going to the middle somewhat than prime to backside. As you possibly can see I attempted spamming the backside
alignment however the views nonetheless animate to the middle of their measurement.
Code snippets:
import Basis
class SquareOptionsContainerViewModel: ObservableObject{
let firstOptionTitle: String
let secondOptionTitle: String
@Printed var firstVoteRatio: Double
@Printed var secondVoteRatio: Double
let firstOptionClickListener: ()->()
let secondOptionClickListener: ()->()
init(firstOptionTitle: String, secondOptionTitle: String, firstVoteRatio: Double, secondVoteRatio: Double, firstOptionClickListener: @escaping () -> Void, secondOptionClickListener: @escaping () -> Void) {
self.firstOptionTitle = firstOptionTitle
self.secondOptionTitle = secondOptionTitle
self.firstVoteRatio = firstVoteRatio
self.secondVoteRatio = secondVoteRatio
self.firstOptionClickListener = firstOptionClickListener
self.secondOptionClickListener = secondOptionClickListener
}
}
ParentView:
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel: SquareOptionsContainerViewModel
var physique: some View {
HStack(spacing: 0.0){
SquareOptionView(title: viewModel.firstOptionTitle, voteRatio: $viewModel.firstVoteRatio, shade: .inexperienced){
viewModel.firstVoteRatio = random(min: 0.0, max: 1.0)
}
Rectangle()
.body(width: 2.0)
.foregroundColor(
.black
)
SquareOptionView(title: viewModel.secondOptionTitle, voteRatio: $viewModel.secondVoteRatio, shade: .crimson){
viewModel.secondVoteRatio = random(min: 0.0, max: 1.0)
}
}
.clipShape(
RoundedRectangle(cornerSize: .init(width: 10.0, peak: 10.0))
)
.overlay(
RoundedRectangle(cornerSize: .init(width: 10.0, peak: 10.0))
.stroke(lineWidth: 2.0)
)
.padding(.vertical, 10.0)
}
func random(min: Double, max: Double) -> Double {
return random * (max - min) + min
}
var random: Double {
return Double(arc4random()) / 0xFFFFFFFF
}
}