我有一个包含许多CALayers的NSView。当用户编辑文档时,这些CALayers会对所有编辑进行动画处理。我正在尝试为我的应用程序实现打印,但是我在正确打印这些CALayers时遇到了一些问题。
一些CALayers边界占据了整个NSView,并且不需要布局,因为它们的位置永远不会改变。但是,我还有一个CALayer,其中包含大约20个小型CALayer。这些CALayers在正常编辑期间为其位置更改设置动画。但是,在尝试打印NSView时,这些小型CALayers永远不会正确布局。我想知道是否有一些特别的事情要确保这些图层正确定位,并允许正确地绘制/打印NSView。
有没有人有打印Core Animation支持的NSView的经验?任何建议都表示赞赏。
答案 0 :(得分:5)
为了解决布局问题,以及使用-renderInContext:
绘制图层层次结构不保留向量元素的事实,我们在Core Plot framework中继承了CALayer。 CPLayer子类重写默认的-drawInContext:
方法以调用我们的自定义-renderAsVectorInContext:
方法(我们为图层执行所有Core Graphics绘图)。要生成用于打印的PDF上下文(或类似),我们使用以下代码调用自定义方法:
-(void)recursivelyRenderInContext:(CGContextRef)context
{
// render self
CGContextSaveGState(context);
[self applyTransform:self.transform toContext:context];
self.renderingRecursively = YES;
if ( !self.masksToBounds ) {
CGContextSaveGState(context);
}
[self renderAsVectorInContext:context];
if ( !self.masksToBounds ) {
CGContextRestoreGState(context);
}
self.renderingRecursively = NO;
// render sublayers
for ( CALayer *currentSublayer in self.sublayers ) {
CGContextSaveGState(context);
// Shift origin of context to match starting coordinate of sublayer
CGPoint currentSublayerFrameOrigin = currentSublayer.frame.origin;
CGRect currentSublayerBounds = currentSublayer.bounds;
CGContextTranslateCTM(context,
currentSublayerFrameOrigin.x - currentSublayerBounds.origin.x,
currentSublayerFrameOrigin.y - currentSublayerBounds.origin.y);
[self applyTransform:self.sublayerTransform toContext:context];
if ( [currentSublayer isKindOfClass:[CPLayer class]] ) {
[(CPLayer *)currentSublayer recursivelyRenderInContext:context];
} else {
if ( self.masksToBounds ) {
CGContextClipToRect(context, currentSublayer.bounds);
}
[currentSublayer drawInContext:context];
}
CGContextRestoreGState(context);
}
CGContextRestoreGState(context);
}
通过并将每个图层渲染到平面核心图形上下文中,保留位置,旋转和其他变换,同时将所有元素渲染为清晰矢量。
尝试渲染图层时需要注意的另一件事是,表示层层次结构的状态可能与内部图层层次结构不同。您可能拥有已应用于移动图层的动画,但图层的position
属性可能尚未更改为匹配。在这种情况下,您应该确保自己动画属性,以便值始终保持同步,或者在动画完成后设置图层中的值。
答案 1 :(得分:0)
最后我调查了一下,无法正确打印CALayers。当时我觉得Core Animation只是为了屏幕设计而不是用于打印(这似乎与它最初是为iPhone设计的事实一致)。
我很想知道我错了。