37
loading...
This website collects cookies to deliver better user experience
GeometryReader { geometry in
Rectangle()
.gesture(DragGesture(coordinateSpace:.local).onChanged( { value in
addPoint(value, geometry:geometry)
})
.onEnded( { value in
endGesture(size:geometry.size)
}))
}
private func addValue(_ value: DragGesture.Value) {
let point = value.location
let size = viewModel.size
// we skip a point if x or y are negative
// or if they are bigger than the width/height
// so we don't draw points outside the view
// I need to store size in the view model
// to avoid the warning
// Modifying state during view update, this will cause undefined behavior.
if point.y < 0 ||
point.y > size.height ||
point.x < 0 ||
point.x > size.width {
viewModel.endPath()
return
}
viewModel.addPoint(value.location)
}
private func endGesture() {
viewModel.endPath()
}
// this is in the view model
func addPoint(_ point:CGPoint) {
var shape = getCurrentShape()
shape.points.append(point)
shapes.removeLast()
shapes.append(shape)
}
struct SimpleShape {
var points:[CGPoint] // points to make a path
var color:Color // stroke color
var width:CGFloat // stroke line width
var id:UUID = UUID() // necessary to use in ForEach
mutating func addPoint(_ point:CGPoint) {
points.append(point)
}
}
var body: some View {
ZStack {
GeometryReader { geometry in
Rectangle()
.gesture(DragGesture(coordinateSpace:.local).onChanged( { value in
addPoint(value, geometry:geometry)
})
.onEnded( { value in
endGesture(size:geometry.size)
}))
}
ForEach(viewModel.shapes, id:\.id) { shape in
DrawShape(points: shape.points)
.stroke(lineWidth: shape.width)
.foregroundColor(shape.color)
}
}
}
struct DrawShape: Shape {
var points: [CGPoint]
func path(in rect: CGRect) -> Path {
var path = Path()
if points.count == 0 {
return path
}
path.move(to: points[0])
for index in 1.. < points.count {
path.addline(to: points[index])
}
return path
}
}
Canvas { context, size in
viewModel.size = size
let frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
for shape in viewModel.shapes {
context.stroke(shape.path(in: frame),
with: .color(.primary),
lineWidth: 5.0)
}
}
.gesture(DragGesture(coordinateSpace:.local).onChanged( { value in
addValue(value)
})
.onEnded( { value in
endGesture()
}))
TimelineView(.periodic(from: Date(), by: 1.0)) { timeContext in
Canvas { context, size in
let date = timeContext.date
var currentPoint = CGPoint(x: 0, y: 0)
var image = context.resolve(Image(systemName: "clock"))
image.shading = .color(.green)
for i in 0..<20 {
var innerContext = context
innerContext.opacity = 0.1 * Double(i)
currentPoint.x += 20
currentPoint.y = offsetFromDate(date: date)
innerContext.draw(image, at: currentPoint)
}
}
}