#ios #swift #cashapelayer #cabasicanimation
Вопрос:
У меня есть циркуляр CAShapeLayer
, в котором я хотел бы при нажатии изменить цвета обводки и заливки. Для этого я добавил a CABasicAnimation
, но , к моему замешательству, анимация на этом не заканчивается toValue
. Вместо этого анимация возвращается к исходному цвету.
Я попытался использовать метод animationDidStop
делегирования при настройке цветов штриха и заливки до нужного конечного цвета, что сработало, но появился мигающий сбой исходных цветов.
Буду признателен за любые рекомендации.
func createCircleShapeLayer() {
let layer = CAShapeLayer()
let circularPath = UIBezierPath(arcCenter: view.center, radius: 50, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)
layer.path = circularPath.cgPath
layer.strokeColor = UIColor.red.cgColor
layer.lineWidth = 10
layer.fillColor = UIColor.clear.cgColor
layer.lineCap = CAShapeLayerLineCap.round
layer.frame = view.bounds
view.layer.addSublayer(layer)
}
func animateLayerOnTap() {
let strokeAnim = CABasicAnimation(keyPath: "strokeColor")
strokeAnim.toValue = UIColor.red.cgColor
strokeAnim.duration = 0.8
strokeAnim.repeatCount = 0
strokeAnim.autoreverses = false
let fillAnim = CABasicAnimation(keyPath: "fillColor")
fillAnim.toValue = UIColor.lightGray.cgColor
fillAnim.duration = 0.8
fillAnim.repeatCount = 0
fillAnim.autoreverses = false
layer.add(fillAnim, forKey: "fillColor")
layer.add(strokeAnim, forKey: "strokeColor")
}
Комментарии:
1. Потому что вы не установили фактический слой в значение toValue. Поэтому, когда анимация заканчивается, она удаляется, чтобы показать, что ваш слой все еще находится там, где он был. О том, как использовать CABasicAnimation, см. Примеры из моей книги, такие как случай 5 в github.com/mattneub/Programming-iOS-Book-Examples/blob/…
Ответ №1:
Анимация UIView довольно чистая и простая в использовании. Когда вы отправляете анимацию UIView на основе блоков, система создает анимацию, которая анимирует свойства вашего представления до их конечных значений, и они остаются там. (Под обложками анимация UIView добавляет одну или несколько анимаций в слой представления и управляет обновлением свойств представления до конечных значений после завершения анимации, но вам не нужно заботиться об этих деталях.)
Ничто из этого не относится к основной анимации. Это сбивает с толку, неинтуитивно и плохо документировано. С помощью основной анимации анимация добавляет временный «слой представления» поверх вашего слоя, который создает иллюзию того, что ваши свойства анимируются от начала до конечного состояния, но это всего лишь иллюзия.
По умолчанию слой презентации удаляется после завершения анимации, и, как вы обнаружили, ваш слой, похоже, возвращается в состояние, предшествующее анимации. Есть настройки, которые вы можете применить, чтобы слой анимации оставался в своем окончательном состоянии после завершения анимации, но сопротивляйтесь желанию сделать это.
Вместо этого вы хотите явно установить свойства вашего слоя в их конечное состояние сразу после запуска анимации. Однако это усложняется тем фактом, что значительное количество свойств слоя «неявно анимированы», что означает, что если вы их измените, система создаст анимацию, которая внесет эти изменения для вас. (В этом случае изменение «прилипает» после завершения неявной анимации.)
Вы анимируете strokeColor и fillColor, которые можно анимировать. Было бы проще воспользоваться неявной анимацией этих свойств слоя. Сложность заключается в том, что если вы хотите изменить какое-либо из значений по умолчанию (например , продолжительность) для неявной анимации, вам нужно вложить изменения в анимируемые свойства между вызовом CATransaction.begin()
и CATransaction.commit()
и использовать вызовы CATransaction для изменения этих значений.
Вот как может выглядеть ваш код для анимации цвета штриха и цвета заполнения вашего слоя с использованием неявной анимации и CATransaction:
CATransaction.begin()
CATransaction.setAnimationDuration(0.8)
layer.strokeColor = UIColor.red.cgColor // Your strokeColor was already red?
layer.fillColor = UIColor.lightGray.cgColor
CATransaction.commit()
Комментарии:
1. «С основной анимацией анимация добавляет временный «слой анимации»», так же как и просмотр анимации. Неправильно предполагать, что они работают по-другому. Анимация просмотра-это анимация слоя.
2. ценю подробное объяснение. в итоге я перешел к заметке Мэтта и установил цвет обводки/заливки слоя сразу после добавления анимации!
3. @Мэтт, справедливое замечание. Но анимация просмотра позаботится о том, чтобы установить свойства представления в их окончательные значения после завершения анимации. В анимации UIView вы задаете свойствам представления новые значения, и система анимирует их в соответствии с этими значениями. Я опустил тот факт, что анимация UIView создает анимацию слоя под обложками для простоты.
4. Я отредактировал свой ответ, чтобы добавить тот факт, что анимация UIView работает, создавая одну или несколько анимаций.