Verhindern Sie die Rückwärtsverfolgung in der iOS-Zeichen-App (Swift)IOS

Programmierung für iOS
Guest
 Verhindern Sie die Rückwärtsverfolgung in der iOS-Zeichen-App (Swift)

Post by Guest »

Ich verwende die SwiftyDraw-Bibliothek, um einen Pfad für meine App zu zeichnen. Das Zeichnen des Pfads funktioniert gut, aber es gibt ein Problem, wenn der Benutzer mit dem Zeichnen des Pfads beginnt und den Finger an derselben Position hin und her bewegt. Es wird immer noch der Pfad gezeichnet und er wird fertiggestellt. Hier habe ich meinen gesamten Code.

Code: Select all

lazy var targetView: UIView = {
let sTargetView =  UIView(frame: CGRect(x: 0,
y: 0,
width: self.view.frame.width,
height: self.view.frame.height/1.3))
sTargetView.center = CGPoint(x: UIScreen.main.bounds.size.width/2,
y: UIScreen.main.bounds.size.height/2)
sTargetView.backgroundColor = .clear
sTargetView.isUserInteractionEnabled = true

canvasView.isUserInteractionEnabled = true
canvasView.backgroundColor = .clear
sTargetView.addSubview(canvasView)
canvasView.brush = .thick
canvasView.brush.color =  self.assistiveTouchSwitch.isOn ? Color(.clear) : Color.init(self.accentColor)
canvasView.frame = sTargetView.bounds
canvasView.delegate = self
return sTargetView
}()
var swiped = false
var lastPoint = CGPoint.zero
var accentColor = UIColor.red//UIColor(hex: "00acc1")
let canvasView = SwiftyDrawView()
var isTutorialAnimationInProgresss = false

var strokeAnimationCounter = 0
var currentPathToTrace : CGPath!
var defaultTransform  = CGAffineTransform()
var assistiveDrawLayersArray = [CAShapeLayer()]
var pathToHitTestAgainst : CGPath!
let dashLayer = CAShapeLayer()
let tutorialLayer = CALayer()
var strokePathsArray = [MyBezierPath]()
var strokeIndex = 0 {
didSet {
self.pathToHitTestAgainst = self.strokePathsArray[strokeIndex].cgPath.copy(strokingWithWidth: 10, lineCap: .round, lineJoin: .round, miterLimit: 0, transform: defaultTransform)
}
}
@IBOutlet weak var assistiveTouchSwitch: UISwitch!

override func viewDidload() {
self.view.addSubview(targetView)
let p1 = MyBezierPath(svgPath: "M 55 20 V 90")
let p2 = MyBezierPath(svgPath: "M 55 47 C 10 18 11 90 55 63")
let p3 = MyBezierPath(svgPath: "M 55 47 C 93 25 94 62 71 73")
let p4 = MyBezierPath(svgPath: "M 35 20 H 80")
strokePathsArray.append(p1)
strokePathsArray.append(p2)
strokePathsArray.append(p3)
strokePathsArray.append(p4)
let combinedPath = CGMutablePath()
combinedPath.addPath(p1.cgPath)
combinedPath.addPath(p2.cgPath)
combinedPath.addPath(p3.cgPath)
combinedPath.addPath(p4.cgPath)
defaultTransform = CGAffineTransform(scaleX: self.targetView.frame.width/109, y: self.targetView.frame.width/109)
let shapeLayer = CAShapeLayer()
shapeLayer.backgroundColor = UIColor.cyan.cgColor
shapeLayer.transform = CATransform3DMakeAffineTransform(defaultTransform)
// The Bezier path that we made needs to be converted to
// a CGPath before it can be used on a layer.
shapeLayer.path = combinedPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 10
shapeLayer.lineCap = .round
shapeLayer.strokeColor = UIColor.white.cgColor
self.targetView.layer.addSublayer(shapeLayer)
self.pathToHitTestAgainst = self.strokePathsArray[0].cgPath.copy(strokingWithWidth: 10, lineCap: .round, lineJoin: .round, miterLimit: 0, transform: defaultTransform)
animatePath()
setUpLayersForAssistiveMode(color: accentColor)
self.targetView.layer.addSublayer(self.canvasView.layer)
}
func setUpLayersForAssistiveMode(color: UIColor){
self.assistiveDrawLayersArray.removeAll()
if self.assistiveTouchSwitch.isOn {
self.strokePathsArray.forEach{
let layer = CAShapeLayer()
layer.path = $0.cgPath
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = 6
layer.strokeStart = 0
layer.strokeEnd = 0
layer.lineCap = .round
layer.strokeColor = color.cgColor
layer.transform = CATransform3DMakeAffineTransform(defaultTransform)
self.targetView.layer.addSublayer(layer)
assistiveDrawLayersArray.append(layer)
}
}
}
func showHint(){
let path = self.strokePathsArray[strokeIndex]
dashLayer.path = path.cgPath
dashLayer.fillColor = UIColor.clear.cgColor
dashLayer.lineDashPattern =  [2,2]
dashLayer.contents = UIImage(named: "pen")?.cgImage
dashLayer.transform = CATransform3DMakeAffineTransform(defaultTransform)
dashLayer.strokeColor = UIColor(hex: "f06292").cgColor
dashLayer.lineWidth = 0.5
self.currentPathToTrace = path.cgPath.copy(strokingWithWidth: 0, lineCap: .round, lineJoin:  .miter, miterLimit: 0, transform: defaultTransform)

if let startPoint = path.startPoint {
let circulPath = UIBezierPath(arcCenter: CGPoint(x: startPoint.x , y: startPoint.y) , radius: 1.5, startAngle: 0, endAngle: 2.0 * CGFloat.pi, clockwise: true)

let circleLayer = CAShapeLayer()
circleLayer.path = circulPath.cgPath
circleLayer.fillColor = UIColor(hex: "f06292").cgColor
circleLayer.transform = CATransform3DMakeTranslation(0, 0, 0)

dashLayer.insertSublayer(circleLayer, at: 0)
}

let secondLastPoint =  path.cgPath.points().count>2 ?  path.cgPath.points()[path.cgPath.points().count-2] : path.cgPath.points()[0]

if let lastPoint = path.cgPath.points().last {
let angle = atan2((lastPoint.y - secondLastPoint.y), (lastPoint.x - secondLastPoint.x))

let distance: CGFloat = 1.0
let path = UIBezierPath()
path.move(to: lastPoint)
path.addLine(to: calculatePoint(from: lastPoint, angle: angle + CGFloat.pi/2, distance: distance)) // to the right
path.addLine(to: calculatePoint(from: lastPoint, angle: angle, distance: distance)) // straight ahead
path.addLine(to: calculatePoint(from: lastPoint, angle: angle - CGFloat.pi/2, distance: distance)) // to the left
path.close()

let  arrowHeadLayer = CAShapeLayer()
arrowHeadLayer.path = path.cgPath
arrowHeadLayer.lineWidth = 1
arrowHeadLayer.strokeColor = UIColor(hex: "f06292").cgColor
arrowHeadLayer.fillColor = UIColor.white.cgColor

dashLayer.insertSublayer(arrowHeadLayer, at: 1)
}
}
func showTutorial(){
if isTutorialAnimationInProgresss {return}   //avoid animation on repeated taps outside boundary

let path = self.strokePathsArray[strokeIndex]
self.tutorialLayer.opacity = 1
tutorialLayer.contents = UIImage(named: "pen")?.cgImage

tutorialLayer.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
tutorialLayer.anchorPoint = CGPoint.zero

let animation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.position))
animation.duration = 1
animation.repeatCount = 0 // just recommended by Apple
animation.path = path.cgPath
animation.calculationMode = .paced
animation.beginTime = 0
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false

CATransaction.begin()
isTutorialAnimationInProgresss = true
CATransaction.setCompletionBlock({
self.tutorialLayer.opacity = 0
self.isTutorialAnimationInProgresss = false
})
tutorialLayer.add(animation, forKey: nil)
CATransaction.commit()
dashLayer.addSublayer(tutorialLayer)
self.targetView.layer.addSublayer(dashLayer)
}
func calculatePoint(from point: CGPoint, angle: CGFloat, distance: CGFloat) ->  CGPoint {
return CGPoint(x: point.x + CGFloat(cosf(Float(angle))) * distance, y: point.y + CGFloat(sinf(Float(angle))) * distance)
}

func animatePath() {
if strokeAnimationCounter == self.strokePathsArray.count { return }

let layer: CAShapeLayer = CAShapeLayer()
layer.strokeColor = self.accentColor.cgColor
layer.lineWidth = 5.0
layer.fillColor = UIColor.clear.cgColor
layer.borderWidth = 0
layer.lineCap = .round
layer.borderColor = UIColor.clear.cgColor
layer.transform = CATransform3DMakeAffineTransform(defaultTransform)
layer.path = self.strokePathsArray[strokeAnimationCounter].cgPath

CATransaction.begin()

let animation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0.0
animation.toValue = 1.0
animation.duration = 1.0

CATransaction.setCompletionBlock { [weak self] in
guard let strongSelf = self else {
print("ViewController was deallocated, stopping animation")
return
}

strongSelf.strokeAnimationCounter += 1
if strongSelf.strokeAnimationCounter  [CGPoint]{
var bezierPoints = [CGPoint]()
self.forEach(body: { (element: CGPathElement) in
let numberOfPoints: Int = {
switch element.type {
case .moveToPoint, .addLineToPoint: // contains 1 point
return 1
case .addQuadCurveToPoint: // contains 2 points
return 2
case .addCurveToPoint: // contains 3 points
return 3
case .closeSubpath:
return 0
}
}()
for index in 0.. Void) {
typealias Body = @convention(block) (CGPathElement) -> Void
func callback(info: UnsafeMutableRawPointer?, element: UnsafePointer) {
let body = unsafeBitCast(info, to: Body.self)
body(element.pointee)
}
let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
self.apply(info: unsafeBody, function: callback)
}}
extension DrawVC: SwiftyDrawViewDelegate{
func swiftyDraw(didCancelDrawingIn drawingView: SwiftyDrawView, using touch: UITouch) {}

func swiftyDraw(shouldBeginDrawingIn drawingView: SwiftyDrawView, using touch: UITouch) -> Bool {
return true
}

func swiftyDraw(didBeginDrawingIn drawingView: SwiftyDrawView, using touch: UITouch) {}

func swiftyDraw(isDrawingIn drawingView: SwiftyDrawView, using touch: UITouch) {
let point = touch.location(in: drawingView)
let iscontain = pathToHitTestAgainst.contains(point)
if iscontain  {
//  print("contains")
if self.assistiveTouchSwitch.isOn {
if let first = self.currentPathToTrace.points().first{
print("distamce:",   first.distance(to: point))
print("length: ", currentPathToTrace.length/2)
if first.distance(to: point)>=21 &&   assistiveDrawLayersArray[strokeIndex].strokeEnd == 0  {
print("from right")
assistiveDrawLayersArray[strokeIndex].strokeEnd = 0
showTutorial()
return
}
}
if let drawItem = drawingView.drawItems.last {
let offset =     drawItem.path.length/(self.currentPathToTrace.length/2)
//                    print(offset)
if offset >= 0.9{
CATransaction.begin()
CATransaction.setDisableActions(false)
assistiveDrawLayersArray[strokeIndex].strokeEnd = 1
CATransaction.commit()
if strokeIndex == strokePathsArray.count-1{
dashLayer.removeFromSuperlayer()
dashLayer.sublayers?.filter{ $0 is CAShapeLayer }.forEach{ $0.removeFromSuperlayer() }
drawingView.clear()
return
}
dashLayer.sublayers?.filter{ $0 is CAShapeLayer }.forEach{ $0.removeFromSuperlayer() }
drawingView.clear()
self.strokeIndex+=1
showHint()
showTutorial()
}else{
CATransaction.begin()
CATransaction.setDisableActions(true)
assistiveDrawLayersArray[strokeIndex].strokeEnd = offset
CATransaction.commit()
print("hello")
}
}
return
}
}else{
//            drawingView.undo()
if self.assistiveTouchSwitch.isOn {
if let drawItem = drawingView.drawItems.last {
let offset =     drawItem.path.length/(self.currentPathToTrace.length/2)
let progress =    Int(max(0, offset))
//                    print (offset)
if progress != 1{
assistiveDrawLayersArray[strokeIndex].strokeEnd = 0
drawingView.clear()
showTutorial()
}
}
return
}
drawingView.undo()
showTutorial()
}
//        print(drawingView.currentPoint)
}

func swiftyDraw(didFinishDrawingIn drawingView: SwiftyDrawView, using touch: UITouch) {
if self.assistiveTouchSwitch.isOn {
if let drawItem = drawingView.drawItems.last {
let offset =     drawItem.path.length/(self.currentPathToTrace.length/2)
let progress =    Int(max(0, offset))
//                    print("progress :", offset)
if progress == 1{
self.assistiveDrawLayersArray[strokeIndex].strokeEnd = 1
if strokeIndex == strokePathsArray.count-1{
dashLayer.removeFromSuperlayer()
dashLayer.sublayers?.filter{ $0 is CAShapeLayer }.forEach{ $0.removeFromSuperlayer() }
drawingView.clear()
return
}
dashLayer.sublayers?.filter{ $0 is CAShapeLayer }.forEach{ $0.removeFromSuperlayer() }
drawingView.clear()
self.strokeIndex+=1
showHint()
showTutorial()
}else{
//                        print("progress : \(progress)")
drawingView.clear()
self.showTutorial()
assistiveDrawLayersArray[strokeIndex].strokeEnd = 0
}
}
return
}else{
//        print(MyBezierPath(cgPath:  strokePath!).length/2)
if let drawItem = drawingView.drawItems.last{
print(currentPathToTrace.length/2 - drawItem.path.length)
if abs(currentPathToTrace.length/2 - drawItem.path.length) >= 17{
drawingView.undo()
showTutorial()
} else {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = 10
layer.lineCap = .round
layer.strokeColor = self.accentColor.cgColor
layer.path = drawItem.path
self.canvasView.layer.addSublayer(layer)

drawingView.clear()

dashLayer.sublayers?.filter{ $0 is CAShapeLayer }.forEach{ $0.removeFromSuperlayer() }

if strokeIndex == strokePathsArray.count-1{
dashLayer.removeFromSuperlayer()
return
}

self.strokeIndex+=1
showHint()
showTutorial()
}
}
}
}}
Der obige Code ist fast der gesamte Code zum Zeichnen eines Pfads.
In func SwiftyDraw(isDrawingIn DrawingView: SwiftyDrawView, Using Touch: UITouch) ist diese Methode in Im Fall der Bedingung self.assistiveTouchSwitch.isOn = true möchte ich verhindern, dass der Benutzer den bereits gezeichneten Pfad zurückverfolgt. Ich habe versucht, den Offset zu überprüfen, um das Problem zu verhindern, aber der Offset verringert seinen Wert nie, selbst wenn der Benutzer rückwärts zeichnet.
Ich bitte jeden Genie, dieses Problem für mich zu lösen. Vielen Dank.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post