Я пытаюсь создать форму FluidView
в SwiftUI, которая действует как жидкость в контейнере, так что, когда устройство находится под определенным углом, форма / «жидкость» тоже. Форма также имеет определенную c емкость, percentFilled
, которая указывает, какая часть родительского представления должна быть заполнена.
Используя эти ограничения, инвариант класса
lines.area == rect.area * percentFilled
, где lines
- четырехугольник, а rect
- ограничивающий прямоугольник. Этот инвариант подразумевает, что «объем» формы остается постоянным для каждого percentFilled
независимо от угла наклона.
Вот что у меня есть на данный момент:
/// A View made using a specified angle and amount to fill
/// - Invariant: The area of the view is exactly equal to the area of the rectangle of the parent view times `percentFilled`
struct FluidView: Shape {
var angle: CGFloat = 0.0
var percentFilled: CGFloat = 0
/// Creates a new FluidView
/// - Parameters:
/// - angle: A value in the range `0...1`. A value of `0` indicates the view is horizontal, and an angle of `1` indicates the view is vertical (horizontal if viewed as landscape)
/// - percentFilled: the amount of the view bounds to fill represented as a value in the range `0...1`. A value of `x` indicates that `x * 100`% of the parent view is covered by this view
init(angle: CGFloat = 0, percentFilled: CGFloat = 0) {
precondition(0...1 ~= angle)
precondition(0...1 ~= percentFilled)
self.angle = angle
self.percentFilled = percentFilled
}
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: 0, y: rect.height * (1 - percentFilled))) // top left
let lines = [
(0, rect.height ), // bottom left
(rect.width * 1 / (1 + angle - percentFilled), rect.height ), // bottom right
(rect.width * 1 / (1 + angle - percentFilled), rect.height * (1 + angle - percentFilled)), // top right
(0, rect.height * (1 - angle - percentFilled)) // top left
].map { x, y in
// make sure no points exceed the bounds
CGPoint(x: min(rect.width, x), y: min(rect.height, y))
}
// invariant
assert(lines.area == rect.area * percentFilled)
path.addLines(lines)
return path
}
}
Мне кажется, То, что у меня есть сейчас, несколько близко к цели, однако инвариант не работает. Я считаю, что мои y-координаты верны, однако я думаю, что мои вычисления для x-координат должны измениться, но я не уверен, что они должны изменить.
Любая помощь будет очень признательна, спасибо !