【问题标题】:graphic context of rotated layers ignores any transformations旋转图层的图形上下文忽略任何变换
【发布时间】:2012-07-24 16:48:57
【问题描述】:

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

例如,如果我有一个包含指向左侧的箭头图像的 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

【问题讨论】:

    标签: iphone objective-c calayer catransform3d


    【解决方案1】:

    The documentation for -[CALayer renderInContext:] 说:

    此方法的 Mac OS X v10.5 实现不 支持整个 Core Animation 合成模型。 QCCompositionLayer、CAOpenGLLayer 和 QTMovieLayer 图层不是 呈现。此外,使用 3D 变换的图层不 渲染,也不是指定背景过滤器,过滤器的图层, compositingFilter 或掩码值。 Mac OS X 的未来版本可能 添加对渲染这些图层和属性的支持。

    (iOS 上也存在此限制。)

    标题CALayer.h 还说:

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

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

    【讨论】:

    • 非常感谢。我会看到做一个解决方法。事实上,我真的不需要任何 3D 旋转,所以我会看看我能用 2D 做什么。
    【解决方案2】:

    你可以用Core Graphaic代替CATransform3DMakeRotation :)

    CGAffineTransform flip = CGAffineTransformMakeScale(1.0, -1.0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2013-05-07
      相关资源
      最近更新 更多