Looking for help on this "weird" problem.
I am using a PanGesture to allow the user to draw a line on CAShapeLayer
.
I keep track of the path until they end and then store the path in an array of paths, clearing their original path from the CAShapeLayer.path
When I redraw those paths onto a UIImage
, the paths are shifted in the Y-axis
towards the top of the screen.
I am attaching two images:
1) The drawing of the path. Drawing The Path
2) The UIImage that is put out when I redraw the path. As you can see, I draw along a grid line, however, when the UIImage is created, the line is above the grid line. The Path Redrawn On UIImage
Any suggestions appreciated.
The code for both the drawing and then the rendering are below.
@objc private func drawLine(_ gestureRecognizer: UIPanGestureRecognizer) {
let point = gestureRecognizer.location(in: self)
if point.x < 0 || point.x > self.bounds.width || point.y < 0 || point.y > self.bounds.height {
return
}
switch gestureRecognizer.state {
case .began:
currentLine = UIBezierPath()
currentLine.lineWidth = settings.defaultSpotRadius
currentLine.lineCapStyle = .round
currentLine.lineJoinStyle = .round
currentLine.move(to: point)
break
case .changed:
currentLine.addLine(to: point)
currentLineDrawLayer.path = currentLine.cgPath
break
case .ended:
self.storage.addLine(clear: fowClearMode, path: currentLine, ofWidth: currentLine.lineWidth)
currentLineDrawLayer.path = nil
storedImage = drawPaths()
break
default:
break
}
}
public func drawPaths() -> UIImage? {
if pathsHidden { return nil }
let rect = CGRect(origin: .zero, size: self.imageSize)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
storedImage.draw(in: rect)
for (isClear, line, width) in thePaths {
let blendMode = isClear ? settings.colorClear : settings.colorDark
line.lineWidth = width
line.stroke(with: blendMode, alpha: 1.0)
}
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
I have created a mini-project that contains only the import bits and pieces. It is available here ... Mini-Project
I think you have a ways to go to get everything working as desired, but, to solve your initial "offset" issue...
In ViewController.swift
you are setting the frame of imgDisplay: ImageDisplay
to self.view.bounds
--- which, in this case, will be 1024 x 768
.
Then in ImageDisplay.swift
you create aPathImage
at a size of 1024 x 791
and setting that image as a sublayer.
Then...
You are tracking pan-gestures based on a view with bounds of 1024 x 768
, then re-drawing those lines on an image that is 1024 x 791
, resulting in a "shift".
Note that, if you change your image size to 800 x 600
the shift will be very obvious, and it will be a little easier to see how it is related to the size difference.
What you probably want to do is set the size of the frame of imgDisplay
to the size of the image.
Try this to see what happens - in ImageDisplay.swift
:
override init(frame: CGRect) {
super.init(frame: frame)
// add this line
self.frame = CGRect(origin: .zero, size: aPathImage.sizeCurrent)
self.contentMode = .center
...
Now, your pan coordinates will match the coordinates of the contained image.
As I said, you've still got a ways to go, but hopefully this helps you along the way.