【问题标题】:pageCurl animation interactive with touchespageCurl 动画与触摸交互
【发布时间】:2019-11-26 05:20:07
【问题描述】:

我正在寻找一种方法来在 UIView 上指示页面卷曲动画,该动画与触摸交互(开始/移动/结束)like this

注意:

  1. 我无法使用 UIPageController。动画应应用于UIView
  2. 动画与触摸开始、触摸移动和触摸结束之间的交互非常重要。就像视频一样

示例代码,但不适用于触摸:

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    BackBtn.layer.cornerRadius = 5.0

    AnimationBtn.layer.cornerRadius = 5.0

    transition.delegate = self
    transition.duration = 1.5
    transition.startProgress = 0
    transition.endProgress = 1
    transition.type = CATransitionType(string: "pageCurl") as String
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.fillMode = kCAFillModeBoth
    transition.isRemovedOnCompletion = false
}

联系移动:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    super.touchesMoved(touches, with: event)

    if let touch = touches.first {

        let endPosition = touch.location(in: touch.view)

        differenceX = startPosition.x - endPosition.x

        differenceY = endPosition.y - startPosition.y

        transition.subtype = kCATransitionFromRight

        touch.view!.layer.add(transition, forKey: kCATransition)

        webView.scrollView.contentOffset = CGPoint(x: nextPage + differenceX, y: 0)
   }
}

【问题讨论】:

    标签: ios swift animation touch page-curl


    【解决方案1】:

    我找到了答案。我只需要更改transition.startProgresstransition.endProgress

    示例代码:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
    
        calculatePageCount()
    
        if let touch = touches.first {
    
            startPosition = touch.location(in: self.view)
    
            endPosition = startPosition
    
            previousPositionX = startPosition.x
    
            print("start x: \(startPosition.x), start y: \(startPosition.y)")
    
            transition.startProgress = 0.0
    
            if index == 0 && startPosition.x > (screenWidth / 2) {
    
                transition.endProgress = 1.0 - Float(startPosition.x / screenWidth)
                transition.subtype = kCATransitionFromRight
    
                self.view.layer.add(transition, forKey: kCATransition)
            } else if index != 0 {
                if index != (pageCounter - 1) && startPosition.x > (screenWidth / 2) {
                    if self.view.layer.animationKeys() != nil {
                        self.view.layer.removeAllAnimations()
                    }
    
                    transition.endProgress = 1.0 - Float(startPosition.x / screenWidth)
                    transition.subtype = kCATransitionFromRight
                    self.view.layer.add(transition, forKey: kCATransition)
                } else if startPosition.x < (screenWidth / 2) {
                    if self.view.layer.animationKeys() != nil {
                        self.view.layer.removeAllAnimations()
                    }
    
                    transition.endProgress = Float(startPosition.x / screenWidth)
                    transition.subtype = kCATransitionFromLeft
                    self.view.layer.add(transition, forKey: kCATransition)
                } else {
                    if self.view.layer.animationKeys() != nil {
                        self.view.layer.removeAllAnimations()
                    }
                }
            } else {
                if self.view.layer.animationKeys() != nil {
                    self.view.layer.removeAllAnimations()
                }
            }
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
    
        if let touch = touches.first {
    
            endPosition = touch.location(in: touch.view)
    
            print("end x: \(endPosition.x), end y: \(endPosition.y)")
    
            differenceX = startPosition.x - endPosition.x
    
            differenceY = endPosition.y - startPosition.y
    
            let differencePosition = endPosition.x - previousPositionX
    
            previousPositionX = endPosition.x
    
            print("difference x: \(differenceX)")
    
            if self.view.layer.animationKeys() != nil {
    
                transition.startProgress = transition.endProgress
    
                if differenceX > 0 {
    
                    differencePosition < 0 ? (transition.endProgress = transition.endProgress + Float((abs(differencePosition) / screenWidth))) : (transition.endProgress = transition.endProgress - Float((abs(differencePosition) / screenWidth)))
    
                    self.view.layer.removeAllAnimations()
                    self.view.layer.add(transition, forKey: kCATransition)
                } else {
    
                    differencePosition > 0 ? (transition.endProgress = transition.endProgress + Float((abs(differencePosition) / screenWidth))) : (transition.endProgress = transition.endProgress - Float((abs(differencePosition) / screenWidth)))
    
                    self.view.layer.removeAllAnimations()
                    self.view.layer.add(transition, forKey: kCATransition)
                }
            }
        }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
    
        print("touch ended")
    
        if self.view.layer.animationKeys() != nil {
    
            if startPosition.x == endPosition.x {
    
                transition.startProgress = transition.endProgress
                transition.endProgress = 0
    
                self.view.layer.removeAllAnimations()
                self.view.layer.add(transition, forKey: kCATransition)
            } else {
    
                if differenceX > 0 {
    
                    if differenceX > (screenWidth / 2) {
    
                        if index < (pageCounter - 1) {
                            index += 1
                        }
                        transition.startProgress = transition.endProgress
                        transition.endProgress = 1
    
                        self.view.layer.removeAllAnimations()
                        self.view.layer.add(transition, forKey: kCATransition)
                    } else {
                        transition.endProgress = 0
    
                        self.view.layer.removeAllAnimations()
                        self.view.layer.add(transition, forKey: kCATransition)
                    }
                } else {
    
                    if abs(differenceX) > (screenWidth / 2) {
                        if index > 0 {
                            index -= 1
    
                            transition.startProgress = transition.endProgress
                            transition.endProgress = 1
    
                            self.view.layer.removeAllAnimations()
                            self.view.layer.add(transition, forKey: kCATransition)
                        } else {
                            transition.endProgress = 0
    
                            self.view.layer.removeAllAnimations()
                            self.view.layer.add(transition, forKey: kCATransition)
                        }
                    } else {
    
                        transition.endProgress = 0
    
                        self.view.layer.removeAllAnimations()
                        self.view.layer.add(transition, forKey: kCATransition)
                    }
                }
            }
        }
        nextPage = CGFloat(index) * webView.scrollView.bounds.size.width
        webView.scrollView.contentOffset = CGPoint(x: nextPage, y: 0)
    }
    
    func calculatePageCount() {
    
        pageCounter = Int((webView.scrollView.contentSize.width / webView.scrollView.bounds.size.width).rounded())
    }
    

    【讨论】: