Как анимировать свойство contentsRect вдоль пути?

#animation #calayer #bounds #cakeyframeanimation

#Анимация #calayer #границы #cakeyframeanimation

Вопрос:

У меня загружен лист спрайтов png и соответствующий файл plist, и я пытаюсь анимировать свойство contentsRect в CALayer для отображения анимации спрайтов из вышеупомянутого листа aprite. Вот код:

 CGFloat width = myLayer.frame.size.width;
CGFloat height = myLayer.frame.size.height;
myLayer.bounds = CGRectMake( 0, 0, width, height );
myLayer.contentsGravity = kCAGravityCenter;
myLayer.contents=(id)pImage; // This is my sprite sheet


CAKeyframeAnimation *keyFrameContentsRectAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contentsRect"];
keyFrameContentsRectAnimation.path = pAnimationPath; // This is a path to animate on
keyFrameContentsRectAnimation.values = pRects; // This is an array of normalized CGRects representing sprite sheet
keyFrameContentsRectAnimation.fillMode = kCAFillModeRemoved;
keyFrameContentsRectAnimation.calculationMode = kCAAnimationDiscrete;
keyFrameContentsRectAnimation.duration=pAnimationDuration;
keyFrameContentsRectAnimation.repeatCount = 1;
  

Приведенный выше код, похоже, работает должным образом, пока я отключаю анимацию пути (т. Е. закомментирую свойство path в keyFrameContentsRectAnimation) — анимация работает, и contentsRect перемещается по моему спрайтовому листу.

Но вот в чем проблема: все мои спрайты требуют некоторого смещения внутри рамки слоя, чтобы моя анимация выглядела правильно (смещение варьируется в зависимости от обрезки прозрачности).

Итак, я подумал, что если я создам путь из этих точек смещения, которые у меня есть, и передам его в свойство path моей анимации, это должно решить проблему. К сожалению, это не тот случай… Как только я добавляю свойство path, вместо анимации спрайтов я вижу изображение всего листа спрайтов на протяжении анимации… Что я пропустил?

Ответ №1:

Что ж, после некоторого чтения и экспериментов у меня есть рабочее решение… Для того, чтобы спрайты отображались в нужных местах, мне пришлось добавить еще одну анимацию в группу анимации и обрезать CALayer до размеров моего спрайта:

 myLayer.bounds = CGRectMake( 0, 0, 256.0, 256.0 ); //my sprite dimentions

myLayer.contentsGravity = kCAGravityCenter;
myLayer.contents=(id)pImage; // This is my sprite sheet


CAKeyframeAnimation *keyFrameContentsRectAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contentsRect"];

keyFrameContentsRectAnimation.values = pRects; // This is an array of normalized CGRects representing sprite sheet
keyFrameContentsRectAnimation.fillMode = kCAFillModeRemoved;
keyFrameContentsRectAnimation.calculationMode = kCAAnimationDiscrete;
keyFrameContentsRectAnimation.duration=pAnimationDuration;
keyFrameContentsRectAnimation.repeatCount = 1;  

CAKeyframeAnimation* kfanim = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
kfanim.path = pAnimationPath;
kfanim.values = pRects;
kfanim.fillMode = kCAFillModeBoth;
kfanim.calculationMode = kCAAnimationDiscrete;
kfanim.duration=pAnimationDuration;
kfanim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];


NSArray *animations = [NSArray arrayWithObjects:keyFrameContentsRectAnimation,
                       kfanim, nil];

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
[animationGroup setDuration:pAnimationDuration];
[animationGroup setRepeatCount: 1];
[animationGroup setAnimations:animations];