带有CALayers的CAAnimation有时会创建闪烁的动画(包括视频) [英] CAAnimation with CALayers occasionally creates flickered animation (video included)

查看:74
本文介绍了带有CALayers的CAAnimation有时会创建闪烁的动画(包括视频)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用拍摄了一张静态照片,并对嘴巴区域进行了动画处理以模仿说话。但是,大约有1/4的时间,一些隐藏的calayer将在整个动画中连续闪烁。

My app takes a still photo and animates the mouth region to emulate talking. However, about 1/4 of the time, some of the hidden calayers will flash continuously throughout the animation.

这是应用程序工作正常
这是小故障时的外观。
编辑:更好的视频

Here is what the app looks like when it works properly. Here is what the app looks like when it glitches. a better video

我假设问题与路径有关。在应用程序中,用户在嘴巴区域(在视频中简要显示)周围创建路径,这将是动画区域。有时,路径会产生平滑的动画,而有时会导致上方的毛刺。此外,如果按后退并尝试向控制器重新加载动画,则毛刺仍然存在,而如果在重新加载之前更改了路径,则偶尔会消失。

I'm assuming the issue is path related. In the app, the user creates a path around the mouth region (shown briefly in the video), and this will be the animated region. Sometimes the path will result in a smooth animation, and other times it will result in the glitch above. Additionally, if I press "back" and try to reload the controller with the animation, the glitch persists, whereas if I change the path before reloading, it occasionally goes away.

如果与路径无关,那么我消除的一些罪魁祸首是:

If it's not path related, some of the culprits I have eliminated are:


  • 图像类型/来源-有时它会对图像a有效,但对图像
    b不起作用,而有时对图像b有效,但对图像b不起作用。我尝试过照片库中的
    图像以及从互联网保存的图像。

  • image type/source -- sometimes it will work for image a but not image b, and other times it will work for image b but not a. I've tried images from photo library as well as ones saved from the internet.

iphone vs模拟器-两个设备均出现问题

iphone vs simulator -- problem occurs on both devices

动画数量的图片-有时会在第一次尝试
时发生;

number of pictures animated -- sometimes it will happen on the first try; other times it will happen on the 5th or 6th try.

下面是从动画视图来看的代码。我首先创建一个全黑的图层,然后创建一个图片减去嘴巴区域的图层,最后是一个仅嘴巴区域的图层。然后,我移动口腔层的位置,以使置换变为黑色,看起来像张开的口腔。

Below is the code from the view to be animated. I first create a layer of all black, followed by a layer with the picture minus the mouth region, and finally a layer of just the mouth region. I then shift the position of the mouth layer, so that the displacement becomes black and looks like an open mouth.

编辑:此外,如果我移开口腔

- (id)initWithFrame:(CGRect)frame leftPt:(CGPoint)point0 rightPt:(CGPoint)point2 vertex1:(CGPoint)vertex1 vertex2:(CGPoint)vertex2 andPicture:(UIImage *)pic{

    self = [super initWithFrame:frame];
    if (self) {

        p0 = point0;
        p2 = point2;
        v1 = vertex1;
        v2 = vertex2;
        picture = pic;

        [self addBlackLayer];
        [self addFaceLayer];
        [self addMouthLayer];

        self.opaque = YES;
    }
    return self;
}
- (void)addBlackLayer {

    CALayer *blackLayer = [CALayer layer];
    blackLayer.frame = self.bounds;
    blackLayer.backgroundColor = [UIColor blackColor].CGColor;
    [self.layer addSublayer:blackLayer];

}
- (void)addFaceLayer {

    CALayer *faceLayer = [CALayer layer];
    faceLayer.frame = self.bounds;
    faceLayer.contents = (id)[picture CGImageWithProperOrientation];
    CAShapeLayer *faceMask = [CAShapeLayer layer];
    CGMutablePathRef fPath = CGPathCreateMutable();
    CGPathMoveToPoint(fPath, NULL, CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds));
    CGPathAddLineToPoint(fPath, NULL, CGRectGetMaxX(self.bounds), CGRectGetMinY(self.bounds));
    CGPathAddLineToPoint(fPath, NULL, CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));
    CGPathAddLineToPoint(fPath, NULL, CGRectGetMinX(self.bounds), CGRectGetMaxY(self.bounds));
    CGPathAddLineToPoint(fPath, NULL, CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds));
    CGPathMoveToPoint(fPath, NULL, p0.x, p0.y);
    midpt = CGPointMake( (p2.x + p0.x)/2, (p2.y+ p0.y)/2);
    CGPoint c1 = CGPointMake(2*v1.x - midpt.x, 2*v1.y - midpt.y); //control points
    CGPoint c2 = CGPointMake(2*v2.x - midpt.x, 2*v2.y - midpt.y);

    CGPathAddQuadCurveToPoint(fPath, NULL, c1.x, c1.y, p2.x, p2.y);
    CGPathAddQuadCurveToPoint(fPath, NULL, c2.x, c2.y, p0.x, p0.y);

    faceMask.path = fPath;
    faceLayer.mask = faceMask;
    [faceMask setFillRule:kCAFillRuleEvenOdd];
    [self.layer addSublayer:faceLayer];
    CGPathRelease(fPath);

}

- (void)addMouthLayer {

    CGMutablePathRef mPath = CGPathCreateMutable();
    CGPathMoveToPoint(mPath, NULL, p0.x, p0.y);
    midpt = CGPointMake( (p2.x + p0.x)/2, (p2.y+ p0.y)/2);
    CGPoint c1 = CGPointMake(2*v1.x - midpt.x, 2*v1.y - midpt.y); //control points
    CGPoint c2 = CGPointMake(2*v2.x - midpt.x, 2*v2.y - midpt.y);

    CGPathAddQuadCurveToPoint(mPath, NULL, c1.x, c1.y, p2.x, p2.y);
    CGPathAddQuadCurveToPoint(mPath, NULL, c2.x, c2.y, p0.x, p0.y);

    self.mouthLayer = [CALayer layer];
    CAShapeLayer *mouthMask = [CAShapeLayer layer];
    self.mouthLayer.frame = self.bounds;
    self.mouthLayer.contents = (id)[picture CGImageWithProperOrientation];
    mouthMask.path = mPath;
    mouthMask.frame = mouthLayer.bounds;
    self.mouthLayer.mask = mouthMask;
    [self.layer addSublayer:mouthLayer];
    self.mouthLayer.frame = CGRectMake(mouthLayer.frame.origin.x, mouthLayer.frame.origin.y, mouthLayer.frame.size.width, mouthLayer.frame.size.height);
    CGPathRelease(mPath);

这是从视图控制器创建动画的代码

Here is the code that creates the animation, from the view controller

- (CAAnimation *)createAnimationWithRepeatCount:(int)count {

    CGPoint convertedStartingCenter = [self.view convertPoint:animatedFace.center toView:animatedFace];
    CGPoint endPt = CGPointMake(convertedStartingCenter.x, convertedStartingCenter.y + 15);

    CABasicAnimation *mouthDown = [CABasicAnimation animationWithKeyPath:@"position"];
    mouthDown.duration = ANIMATION_TIME;
    mouthDown.beginTime = 0;
    mouthDown.fromValue = [NSValue valueWithCGPoint:convertedStartingCenter];
    mouthDown.toValue = [NSValue valueWithCGPoint:endPt];

    CABasicAnimation *mouthUp = [CABasicAnimation animationWithKeyPath:@"position"];
    mouthUp.duration = ANIMATION_TIME;
    mouthUp.beginTime = ANIMATION_TIME;
    mouthUp.fromValue = [NSValue valueWithCGPoint:endPt];
    mouthUp.toValue = [NSValue valueWithCGPoint:convertedStartingCenter];

    CAAnimationGroup *totalAnimation = [CAAnimationGroup animation];
    [totalAnimation setAnimations:[NSArray arrayWithObjects:mouthDown,mouthUp, nil]];
    [totalAnimation setDuration:2*ANIMATION_TIME];
    [totalAnimation setRemovedOnCompletion:NO];
    [totalAnimation setFillMode:kCAFillModeForwards];
    totalAnimation.repeatCount = count;

    return totalAnimation;

}


推荐答案

方法(不知道是否尝试过),则只能使用 CABasicAnimation 并将类设置为动画委托,在委托方法中,您可以尝试启动下一个 CABasicAnimation 。如果您没有尝试过,我可以为您提供示例。

Just another approach (don't know if you tried), you could use only CABasicAnimation and set your class as the animation delegate, and in the delegate method you could try to start the the next CABasicAnimation. If you didn't tried I can provide an example for you.

这篇关于带有CALayers的CAAnimation有时会创建闪烁的动画(包括视频)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆