当任何其他动画发生时,CAShapeLayer 会重绘自己吗?

Posted

技术标签:

【中文标题】当任何其他动画发生时,CAShapeLayer 会重绘自己吗?【英文标题】:CAShapeLayer redraws itself when any other animation occurs? 【发布时间】:2012-11-16 19:11:28 【问题描述】:

我有一个由CGMutablePaths 组成的图形。我正在使用这些CGMutablePaths,并根据它们所代表的图形的不同区域将它们分成CAShapeLayers。以下是用于完成此操作的代码的 sn-p:

_initialSize = _size = CGSizeMake(168.784,127.842);
CGRect shapeLayerFrame = CGRectMake(0, 0, _initialSize.width, _initialSize.height);

CAShapeLayer *eyeBallShapeLayer = [[CAShapeLayer alloc] init];
eyeBallShapeLayer.fillColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1].CGColor;
eyeBallShapeLayer.bounds = shapeLayerFrame;
CGMutablePathRef eyeBallMutablePath = CGPathCreateMutable();

CAShapeLayer *eyeWhiteShapeLayer = [[CAShapeLayer alloc] init];
eyeWhiteShapeLayer.fillColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor;
eyeWhiteShapeLayer.bounds = shapeLayerFrame;
CGMutablePathRef eyeWhiteMutablePath = CGPathCreateMutable();

CGMutablePathRef mutablePath;

mutablePath = CGPathCreateMutable();
CGPathMoveToPoint(mutablePath, NULL, 168.78,127.79);
CGPathAddLineToPoint(mutablePath, NULL, 155.56,127.13);
CGPathAddCurveToPoint(mutablePath, NULL, 156.23,126.83,156.73,125.92,157.06,125.31);
CGPathAddCurveToPoint(mutablePath, NULL, 157.60,122.36,157.84,119.11,159.77,116.67);
CGPathAddCurveToPoint(mutablePath, NULL, 160.75,115.23,160.44,113.42,160.52,111.78);
CGPathAddCurveToPoint(mutablePath, NULL, 160.58,111.83,160.64,111.88,160.70,111.94);
CGPathAddCurveToPoint(mutablePath, NULL, 161.05,112.27,161.27,112.68,161.47,113.10);
CGPathAddCurveToPoint(mutablePath, NULL, 161.63,113.46,161.78,113.82,161.96,114.16);
CGPathAddCurveToPoint(mutablePath, NULL, 161.97,114.18,161.98,114.20,161.99,114.21);
CGPathAddCurveToPoint(mutablePath, NULL, 162.13,114.47,162.29,114.71,162.51,114.92);
CGPathAddLineToPoint(mutablePath, NULL, 162.52,114.92);
CGPathAddCurveToPoint(mutablePath, NULL, 162.96,115.28,163.36,115.65,163.74,116.05);
CGPathAddCurveToPoint(mutablePath, NULL, 165.44,117.86,166.53,120.17,167.18,122.59);
CGPathAddCurveToPoint(mutablePath, NULL, 167.25,122.86,167.32,123.13,167.38,123.40);
CGPathAddCurveToPoint(mutablePath, NULL, 167.63,124.48,167.79,125.58,167.89,126.67);
CGPathAddCurveToPoint(mutablePath, NULL, 167.90,126.94,168.05,127.13,168.23,127.30);
CGPathAddCurveToPoint(mutablePath, NULL, 168.41,127.47,168.63,127.62,168.78,127.79);
CGPathCloseSubpath(mutablePath);
CGPathAddPath(eyeBallMutablePath, NULL, mutablePath);
CGPathRelease(mutablePath);


//a whole lot of paths being loaded in much the same way as above

_shapeLayers = [[NSMutableArray alloc] init];

eyeBallShapeLayer.path = eyeBallMutablePath;
[_shapeLayers addObject:eyeBallShapeLayer];
CGPathRelease(eyeBallMutablePath);
[eyeBallShapeLayer release];

eyeWhiteShapeLayer.path = eyeWhiteMutablePath;
[_shapeLayers addObject:eyeWhiteShapeLayer];
CGPathRelease(eyeWhiteMutablePath);
[eyeWhiteShapeLayer release];

我将这些 shapeLayers 附加到视图 layer 属性,并且图形绘制得很好。我遇到的问题是CAShapeLayers 在发生任何动画时都会重新绘制自己。 IE 如果一个模态视图被拉起或者有一个导航转换,它会重绘自己。我有当用户点击屏幕(如照片应用程序)时条形消失的功能,并且在此期间它会重新绘制自己。当我拖动形状时,它也会重新绘制自己。对于我的一些具有大量路径的图形,它会导致动画在重绘自身时出现断断续续的现象。

所以我的问题是,有人知道为什么会这样吗?我做错了什么导致这种情况发生?当我只是在drawRect中绘制图形时没有发生这种情况,所以我有点困惑。

【问题讨论】:

【参考方案1】:

默认情况下,动画中的每一帧都会重绘CALayer。你需要做的是告诉你的层他们应该是rasterized。通过这样做,您的图层只会在图层内容发生变化时重绘,而不是在它涉及动画时重绘。

如果您为每个形状图层添加以下代码,动画应该会运行得更加流畅。

[shapeLayer setRasterizationScale:[[UIScreen mainScreen] scale]];
[shapeLayer setShouldRaseterize:YES];

【讨论】:

谢谢。它是否应该在它不参与的动画的每一帧中重新绘制?我确实尝试了您上面提到的方法,它有助于提高性能,但它仍然在重绘自身并结结巴巴。 技术上它与动画有关。为了显示/隐藏模态视图,它需要在屏幕上绘制或多或少的图层。对于导航转换,它需要改变它在屏幕上的绘制位置。您可以尝试做的一件事是为 shapeLayers 所在的图层添加上述代码,并为 shapeLayers 删除它。这样一来,只需栅格化一层而不是多层。

以上是关于当任何其他动画发生时,CAShapeLayer 会重绘自己吗?的主要内容,如果未能解决你的问题,请参考以下文章

当大量磁盘活动发生时如何使 Linux GUI “可用”

UIView 动画完成块在其他动画开始时触发

如何使用 CAShapeLayer 使我的 UIBezierPath 动画?

wpf数据绑定发生时如何显示加载图形/动画

当我的 UIPanGestureRecognizer 与 UIScrollView 一起发生时,如何取消其他事件?

《每周一点canvas动画》——用户交互