Чтобы обойти проблемы с макетом, а также тот факт, что использование -renderInContext:
для рисования иерархии слоев не сохраняет векторные элементы, мы подклассифицировали CALayer в Core Plot framework . Подкласс CPLayer переопределяет метод -drawInContext:
по умолчанию для вызова нашего пользовательского метода -renderAsVectorInContext:
(где мы выполняем все наши базовые графические рисунки для слоя). Чтобы создать 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);
}
Это проходит и визуализирует каждый слой в плоский контекст Core Graphics, сохраняя положение, вращение и другие преобразования, в то время как все элементы отображаются в виде резких векторов.
Еще одна вещь, на которую следует обратить внимание при попытке рендеринга слоев, - это то, что состояние вашей иерархии уровня представления может не совпадать с вашей внутренней иерархией слоя. У вас могут быть анимации, которые были применены для перемещения ваших слоев, но свойства position
слоев не могли быть изменены для соответствия. В этом случае вам следует убедиться, что вы либо сами анимируете свойства, чтобы значения всегда оставались синхронизированными, либо устанавливаете значения в вашем слое после завершения анимации.