One thing I have noticed is the Canvas code doesn't run until there's a gesture, and I'm not sure why that is because the documentation has an example that displays a drawing upon loading the Canvas.
struct Line {
var points: [CGPoint]
var color: Color
}
var body: some View {
@State var lines: [Line] = []
Canvas { ctx, size in
for line in lines {
let color = line.colorName == nil ? getColor(colorName: nil, rgb: line.rgb) : getColor(colorName: line.colorName, rgb: nil)
var path = Path()
print(line.points) // this is how I noticed this code doesn't run until the gesture runs. This print statement doesn't run upon loading the Canvas
path.addLines(line.points)
ctx.stroke(path, with: .color(color), style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
draw(position: value.location, translation: value.translation)
}
})
)
.onAppear {
lines = parseLinesString()
for line in lines {
for point in line.points {
draw(position: point, translation: nil)
}
}
}
func draw(position: CGPoint, translation: CGSize?) {
if translation == .zero || translation == nil {
lines.append(Line(points: [position], color: color.black))
} else {
guard let lastIndex = lines.indices.last else {
return
}
lines[lastIndex].points.append(position)
unsaved = true
}
}
}
As I mentioned previously, I'm not sure how to translate the documentation example to my application. If anyone could point me in the right direction that would be greatly appreciated. Thank you.
Post
Replies
Boosts
Views
Activity
@Claude31 Thank you for your response. Below is revised code, with the ScrollView implemented, so the drawing aspect isn't going to work unless that's removed. I put a comment in .onAppear { } where I'm assuming code needs to be written to plot the points from lines onto the canvas. I looked at the official documentation for canvas' that draws upon loading but I can't seem to figure out how to apply it to what I'm doing.
import SwiftUI
struct LineData {
var points: [CGPoint]
var color: Color
}
struct CanvasExample: View {
@State var lines: [LineData] = []
@State var selectedColor: Color = Color.black
var body: some View {
ScrollView (showsIndicators: false) {
VStack {
Canvas { ctx, size in
for line in lines {
var path = Path()
path.addLines(line.points)
ctx.stroke(path, with: .color(line.color), style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))
}
}.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
let position = value.location
if value.translation == .zero {
lines.append(LineData(points: [position], color: selectedColor))
} else {
guard let lastIndex = lines.indices.last else {
return
}
lines[lastIndex].points.append(position)
}
})
)
.onAppear {
// code that takes data passed to variable lines and draws on canvas
}
}
}
}
}
#Preview {
CanvasExample()
}
Thank you.
I have two follow up questions. Any help would be greatly appreciated.
How can I implement a scroll feature with the Canvas so that the Canvas itself would be larger than the screen?
How can I draw on the canvas upon loading the canvas? For example, if I pass data stored as a Line variable to the view that the Canvas is on, how can I draw onto the canvas upon loading based off of that data?
Thank you.
@sha921 @thibautrichez Thank you for your responses. I get the following errors with the code below:
Button {
login()
} label: {
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill(Color.black)
.frame(width: UIScreen.main.bounds.width - 50, height: 50)
Text("Sign in")
.foregroundColor(.white)
}
}
func login() {
print("test")
}
Incorrect argument label in call (have '_: label:', expected 'value:selected:')
Trailing closure passed to parameter of type 'String' that does not accept a closure
Thank you again for the help so far.