OStack程序员社区-中国程序员成长平台

标题: ios - CALayer 中的平滑动画孔? [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 17:24
标题: ios - CALayer 中的平滑动画孔?

好的,我根据 SO 上的各种帖子想出了如何做到这一点,而且效果很好。我正在研究一个覆盖层,它基本上会掩盖整个窗口,除了一个小区域。这是为了引起对我应用程序特定区域的关注。我正在使用一堆对 moveToPoint:addLineToPoint: 的调用(这是在我的 CALayer 子类的 drawInContext: 中):

....

// inner path (CW)
[holePath moveToPoint:CGPointMake(x, y)];
[holePath addLineToPoint:CGPointMake(x + w, y)];
[holePath addLineToPoint:CGPointMake(x + w, y + h)];
[holePath addLineToPoint:CGPointMake(x, y+h)];

// outer path (CCW)
[holePath moveToPoint:CGPointMake(xBounds, yBounds)];
[holePath addLineToPoint:CGPointMake(xBounds, yBounds + hBounds)];
[holePath addLineToPoint:CGPointMake(xBounds + wBounds, yBounds + hBounds)];
[holePath addLineToPoint:CGPointMake(xBounds + wBounds, yBounds)];

// put the path in the context
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0, 0);
CGContextAddPath(ctx, holePath.CGPath);
CGContextClosePath(ctx);

// set the color
CGContextSetFillColorWithColor(ctx, self.overlayColor.CGColor);

// draw the overlay
CGContextDrawPath(ctx, kCGPathFillStroke);

(holePathUIBezierPath 的一个实例。)

到目前为止一切顺利。下一步是动画。为了做到这一点(我也在 SO 上找到了这个技术)我做了一个方法如下

-(CABasicAnimation *)makeAnimationForKeyNSString *)key {
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:key];
    anim.fromValue = [[self presentationLayer] valueForKey:key];
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    anim.duration = 0.5;

    return anim;
}

并覆盖actionForKey:initWithLayer:needsDisplayForKey:(返回makeAnimationForKey:的结果在actionForKey:。现在,我得到了一个不错的“洞层”,它有一个属性 holeRect 可以使用隐式 CAAnimations 进行动画处理!不幸的是,它非常不稳定。我得到了类似 2或每秒3帧。我认为可能是背景的问题,并尝试将其替换为快照,但没有骰子。然后,我使用 Instruments 进行分析,发现这里的 HUGE hog 是对 的调用CGContextDrawPath().

tl;dr 我想我的问题归结为:有没有更简单的方法来创建这个层,其中有一个孔,可以更快地重绘?我的直觉是,如果我可以简化我正在使用的路径,那么绘制路径会更轻松。或者可能掩盖?请帮忙!



Best Answer-推荐答案


好的,我尝试了 phix23 的建议,它完全成功了!起初,我将 CALayer 子类化并添加一个 CAShapeLayer 作为子层,但我无法让它正常工作,此时我已经很累了,所以我放弃了,只是用 CAShapeLayer 完全替换了我的子类!我在自己的方法中使用了上面的代码,返回 UIBezierPath,并像这样动画:

UIBezierPath* oldPath = [self pathForHoleRect:self.holeRect];
UIBezierPath* newPath = [self pathForHoleRect:rectToHighlight];
self.holeRect = rectToHighlight;

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath"path"];
animation.duration = 0.5;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = (id)oldPath.CGPath;
animation.toValue = (id)newPath.CGPath;
[self.holeLayer addAnimation:animation forKey"animatePath"];
self.holeLayer.path = newPath.CGPath;

有趣的附注——path 不是隐式可动画的。我想这是有道理的。

关于ios - CALayer 中的平滑动画孔?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13080440/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4