iphone - 旋转图层的图形上下文忽略任何变换

标签 iphone objective-c calayer catransform3d

我正在由多个图层组成一个 View ,其中一些图层是旋转的。这些图层的显示效果非常好,但是当我尝试制作图像时,所有旋转/变换都会被忽略。

例如,如果我有一个 CALayer,其中包含指向左侧的箭头图像,则在绕 z 轴旋转(使用 CATransform3DMakeRotation)后,它指向顶部,并且该图层会正确显示。但是,如果我获得该层的图像(使用 renderInContext),箭头仍然指向左侧,忽略任何转换。

有人知道为什么吗?我需要做什么才能得到我想要的结果? :-)

示例代码:

//  ViewController.m

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

// Don't forget to add the QuartzCore framework to your target.

@interface ViewController ()
@end

@implementation ViewController

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.view.backgroundColor = [UIColor lightGrayColor];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // Get the arrow image (tip to the left, 50 x 50 pixels).
    // (Download the image from here: http://www.4shared.com/photo/uQfor7vC/arrow.html )
    UIImage *arrowImage = [UIImage imageNamed:@"arrow"];

    // The arrow layer in it's starting orientation (tip to the left).
    CGRect layerFrame = CGRectMake(50.0, 50.0, arrowImage.size.width, arrowImage.size.height);
    CALayer *arrowLayerStart = [CALayer new];
    arrowLayerStart.frame = layerFrame;
    [arrowLayerStart setContents:(id)[arrowImage CGImage]];
    [self.view.layer addSublayer:arrowLayerStart];

    // The arrow layer rotated around the z axis by 90 degrees.
    layerFrame.origin = CGPointMake(layerFrame.origin.x + layerFrame.size.width + 25.0, layerFrame.origin.y);
    CALayer *arrowLayerZ90 = [CALayer new];
    arrowLayerZ90.frame = layerFrame;
    [arrowLayerZ90 setContents:(id)[arrowImage CGImage]];
    arrowLayerZ90.transform = CATransform3DMakeRotation(M_PI/2.0, 0.0, 0.0, 1.0);
    [self.view.layer addSublayer:arrowLayerZ90];

    // Now make images of each of these layers and display them in a second row.

    // The starting layer without any rotation.
    UIGraphicsBeginImageContext(arrowLayerStart.frame.size);
    [arrowLayerStart renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *arrowStartImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    layerFrame.origin = CGPointMake(arrowLayerStart.frame.origin.x,
                                    arrowLayerStart.frame.origin.y + arrowLayerStart.frame.size.height + 25.0);
    CALayer *arrowLayerStartCaptured = [CALayer new];
    arrowLayerStartCaptured.frame = layerFrame;
    [arrowLayerStartCaptured setContents:(id)[arrowStartImage CGImage]];
    [self.view.layer addSublayer:arrowLayerStartCaptured];

    // The second layer, rotated around the z axis by 90 degrees.
    UIGraphicsBeginImageContext(arrowLayerZ90.frame.size);
    [arrowLayerZ90 renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *arrowZ90Image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    layerFrame.origin = CGPointMake(arrowLayerZ90.frame.origin.x,
                                    arrowLayerZ90.frame.origin.y + arrowLayerZ90.frame.size.height + 25.0);
    CALayer *arrowLayerZ90Captured = [CALayer new];
    arrowLayerZ90Captured.frame = layerFrame;
    [arrowLayerZ90Captured setContents:(id)[arrowZ90Image CGImage]];
    [self.view.layer addSublayer:arrowLayerZ90Captured];    
}

@end


//  ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@end


//  AppDelegate.h

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end


//  AppDelegate.m

#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate
@synthesize window = _window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController = [[ViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}

@end

最佳答案

The documentation for -[CALayer renderInContext:]说:

The Mac OS X v10.5 implementation of this method does not support the entire Core Animation composition model. QCCompositionLayer, CAOpenGLLayer, and QTMovieLayer layers are not rendered. Additionally, layers that use 3D transforms are not rendered, nor are layers that specify backgroundFilters, filters, compositingFilter, or a mask values. Future versions of Mac OS X may add support for rendering these layers and properties.

(iOS 上也存在此限制。)

header CALayer.h 还表示:

 * WARNING: currently this method does not implement the full
 * CoreAnimation composition model, use with caution. */

本质上,-renderInContext:在一些简单的情况下很有用,但在更复杂的情况下不会按预期工作。您将需要找到其他方法来进行绘图。 Quartz(核心显卡)适用于 2D,但对于 3D,你就得靠自己了。

关于iphone - 旋转图层的图形上下文忽略任何变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11635603/

相关文章:

iphone - 如何使用 Core Location 计算速度?

iphone - UIWebView webViewDidStartLoad 有时不触发

objective-c - NSFetchedResultsController 帮助

ios - 使用多个 CALayer 蒙版时的性能问题

iphone - 分发证书错误:"This certificate is not yet valid."

ios - 如何解决 xcode 中冲突的配置设置?

ios - iCarousel + UITableView = cellForRowAtIndexPath indexPath 始终为空

ios - 如果结果使用 NSLog 记录,如何创建单元测试

ios - 向 CAlayer 添加带消失点投影的扭曲

ios - CAGradientLayer 超出 UILabel 的框架