pageCurl 动画与触摸交互
pageCurl animation interactive with touches
我正在寻找一种方法来在 UIView
上指示与触摸交互的卷页动画 (Began/Moved/Ended) like this
注:
- 我无法使用 UIPageController。动画应应用于
UIView
.
- 动画与触摸开始、触摸移动和触摸结束的交互非常重要。跟视频一模一样
示例代码但不适用于触摸:
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)
}
}
我找到了答案。我只需要更改 transition.startProgress
和 transition.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())
}
我正在寻找一种方法来在 UIView
上指示与触摸交互的卷页动画 (Began/Moved/Ended) like this
注:
- 我无法使用 UIPageController。动画应应用于
UIView
. - 动画与触摸开始、触摸移动和触摸结束的交互非常重要。跟视频一模一样
示例代码但不适用于触摸:
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)
}
}
我找到了答案。我只需要更改 transition.startProgress
和 transition.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())
}