CAShapeLayer странное поведение в первый раз анимации
Я написал эту анимацию для CAShapeLayer (pulseLayer) и в viewDidLoad()
:
let pulseLayer = CAShapeLayer()
@IBOutlet weak var btnCart: UIButton!
override func viewDidLoad() {
let longpress = UILongPressGestureRecognizer(target: self, action: #selector(CategoryViewController.longPressGestureRecognized(_:)))
tableView.addGestureRecognizer(longpress)
heartBeatAnimation.duration = 0.75
heartBeatAnimation.repeatCount = Float.infinity
heartBeatAnimation.autoreverses = true
heartBeatAnimation.fromValue = 1.0
heartBeatAnimation.toValue = 1.2
heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
btnCart.layer.addSublayer(pulseLayer)
}
func addBtnCartLayerWithAnimation() {
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnCart.frame.midX, y: btnCart.frame.midY), radius: btnCart.frame.width * 1.5, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
pulseLayer.path = ovalPath.cgPath
pulseLayer.opacity = 0.15
pulseLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pulseLayer.bounds = ovalPath.cgPath.boundingBox
pulseLayer.add(heartBeatAnimation, forKey: "heartBeatAnimation")
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1.0)
}
и функция removeLayer:
func removeLayer() {
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 0.1, 0.1, 0.1)
pulseLayer.removeAllAnimations()
}
Проблема в том, что первая анимация слоя идет снизу!
первая анимация после viewDidLoad
затем после этого любой вызов для этой анимации начинается с центра (определенной точки привязки)
Кто-нибудь может сказать мне, почему это происходит?
весь класс, где я определил и использовал UILongGestureRecognizer
на tableView для запуска / остановки анимации:
func longPressGestureRecognized(_ gestureRecognizer: UIGestureRecognizer) {
let longPress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longPress.state
let locationInView = longPress.location(in: tableView)
let indexPath = tableView.indexPathForRow(at: locationInView)
switch state {
case UIGestureRecognizerState.began:
if indexPath != nil {
addBtnCartLayerWithAnimation()
}
case UIGestureRecognizerState.changed:
// some code here not related to the animation
default:
removeLayer()
}
}
1 ответ
При использовании автономных слоев (слоев, которые не являются резервным хранилищем UIView
), неявные анимации добавляются для каждого анимируемого изменения свойства.
Вы видите этот эффект, потому что слой анимирует свои свойства от нуля до начальных значений, которые вы устанавливаете в addBtnCartLayerWithAnimation()
,
Что вы хотите сделать, это установить эти начальные значения без анимации (что должно быть сделано явно). Вы можете обернуть изменение в транзакции, в которой вы отключаете анимацию, следующим образом:
CATransaction.begin()
CATransaction.setDisableActions(true)
pulseLayer.path = ovalPath.cgPath
pulseLayer.opacity = 0.15
pulseLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pulseLayer.bounds = ovalPath.cgPath.boundingBox
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1.0)
CATransaction.commit()
pulseLayer.add(heartBeatAnimation, forKey: "heartBeatAnimation")