Domanda

I have been looking far and wide for the answer. I'm still coming up to speed on iOS dev, so I can definitely accept that I may be clooless here. However, the complete and utter lack of answers out there makes me wonder if there actually is an answer.

Here's the deal: I am using a CGLayer to generate a fairly basic vector polygon:

- (CGLayerRef)getASegment
{
    CGSize  layerSize = s_viewRects[kASegment].size;

    CGLayerRef  theLayer = CGLayerCreateWithContext ( UIGraphicsGetCurrentContext(),
        layerSize, nil );

    CGContextRef context = CGLayerGetContext ( theLayer );

    CGContextAddLines ( context, s_shapePoints, 7 );

    return theLayer;
}

s_viewRects is a static array that holds the container rects, as placed in the overall image, and s_shapePoints contains an array of CGPoint structs that maps out a distorted hexagon.

Now, I want to re-use this shape. It needs to be flipped and rotated in order to fit all the uses (for the record, these are "segments" in an "LED" display).

I get the shape fine. No problem.

The problem is in rotating it for re-use. There doesn't seem to be any way to actually rotate a CGLayer. Lots of ways to rotate CALayers, but not CGLayers. I'd be happy to use a CALayer, except that CALayers seem to be all focused on raster graphics, and I need vector graphics.

I'm sure there must be an obvious way to address this. The only way that I have seen, so far, is to rotate the entire target graphics context, draw the shape, then un-rotate the context. The equivalent of turning the house to unscrew a lightbulb.

The only way that I can get it to work, is to actually transform the points before drawing each segment separately, which means no re-use. Doing a CGContextRotateCTM during the creation of the shape does not actually result in a rotated element when displayed.

Any clues?

È stato utile?

Soluzione

The only way that I have seen, so far, is to rotate the entire target graphics context, draw the shape, then un-rotate the context. The equivalent of turning the house to unscrew a lightbulb.

I'm pretty certain that is your solution. It's how drawing with CGContextRef works.

I'd be happy to use a CALayer, except that CALayers seem to be all focused on raster graphics, and I need vector graphics.

Have you tried using a CAShapeLayer?

Altri suggerimenti

OK, as promised, here is the code.

First, I use a CAShapeLayer, and create it in a manner similar to above:

- (CALayer *)getSegment
{
    CGRect  layerFrame = CGRectMake ( 0, 0, s_viewRects[kASegment].size.width, s_viewRects[kASegment].size.height );

    CAShapeLayer    *ret = [CAShapeLayer layer];

    [ret setFrame:layerFrame];

    CGMutablePathRef    thePath = CGPathCreateMutable ();

    CGPathAddLines ( thePath, nil, s_shapePoints, 7 );

    [ret setPath:thePath];

    return ret;
}

Then, I set it into a main layer, like so, doing the transform along the way:

_top_left_element = [self getSegment];

frame = [self calculateRectForElement:_top_left_element];

CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI_2, 0.0, 0.0, -1.0 );

[_top_left_element setTransform:transform];
[_top_left_element setFrame:frame];
[_main_element addSublayer:_top_left_element];

The CATransform3DRotate is necessary, as the transform property of the layer is a 3D one. I use M_PI_2, as all transforms are in Radians (M_PI_2 is a convenient macro that means "90°"), and the -1 will make the rotate go counter-clockwise.

calculateRectForElement is a function that figures out where everything is placed. It simply returns a rect that positions the element.

_top_left_element is a class property that is a CALayer*.

I did this, and Bjorn Strongintheram's your uncle.

UPDATE: I wanted to add that you need to make sure that you CGPathRelease the layer's paths in the unload/destruct, or you will get a leak.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top