CALayer如何将点转换为子层?

时间:2013-11-29 13:25:30

标签: ios core-animation transformation

让我们假设我们有一个2D空间(以简化情况),以及层S和层C,其中C是S的子层。 转换过程必须影响边界,C的位置,C的变换,S的sublayersTransform,C的anchorPoint。我的猜测是下一个:

CGAffineTransform transformToChild(CALayer *S, CALayer *C) {
    CGFloat txa = - C.bounds.origin.x - C.bounds.size.width * C.anchorPoint.x;
    CGFloat tya = - C.bounds.origin.y - C.bounds.size.height * C.anchorPoint.y;

    CGFloat txb = C.position.x;
    CGFloat tyb = C.position.y;

    CGAffineTransform sublayerTransform = CATransform3DGetAffineTransform(S.sublayerTransform);
    CGAffineTransform fromS = CGAffineTransformTranslate(sublayerTransform, txb, tyb);
    fromS = CGAffineTransformConcat(fromS, C.affineTransform);
    fromS = CGAffineTransformTranslate(fromS, txa, tya);

    return fromS;
}

但是当子图层的变换不是标识时(例如,在旋转到M_PI_2角度的情况下),这不起作用。 带有图层的整个代码:

CALayer *l1 = [CALayer new];
l1.frame = CGRectMake(-40, -40, 80, 80);
l1.bounds = CGRectMake(40, 40, 80, 80);
CALayer *l2 = [CALayer new];
l2.frame = CGRectMake(50, 40, 20, 20);
l2.bounds = CGRectMake(40, 40, 20, 20);
CGAffineTransform t2 = CGAffineTransformMakeRotation(M_PI / 2);
l2.affineTransform = t2;
[l1 addSublayer:l2];

CGAffineTransform toL2 = transformToChild(l1, l2);
CGPoint p = CGPointApplyAffineTransform(CGPointMake(70, 50), toL2);
NSLog(@"Custom Point %@", [NSValue valueWithCGPoint:p]);

p = [l1 convertPoint:CGPointMake(70, 50) toLayer:l2];
NSLog(@"CoreAnimation Point %@", [NSValue valueWithCGPoint:p]);

与系统结果的比较:

Custom Point NSPoint: {-50, 80}
CoreAnimation Point NSPoint: {50, 40}

2 个答案:

答案 0 :(得分:1)

这里有一个旧的邮件列表主题,其中包含一些有关此内容的详细信息:

这些消息很旧,所以例如它们不包括几乎最近添加的geometryFlipped属性的效果,但这只会在合并矩阵上添加另一个术语。

答案 1 :(得分:0)

所以,我发现了这种与子层坐标空间的点转换方式,它可以与子层的非标识转换一起正常工作。 sublayers这里没有介绍超级层的变换,但我认为扩展这些功能并不难以支持它。

CGPoint pointToChild(CALayer *C, CGPoint p) {

    CGFloat txa = - C.bounds.origin.x - C.bounds.size.width * C.anchorPoint.x;
    CGFloat tya = - C.bounds.origin.y - C.bounds.size.height * C.anchorPoint.y;

    CGFloat txb = C.position.x;
    CGFloat tyb = C.position.y;

    p.x -= txb;
    p.y -= tyb;

    p = CGPointApplyAffineTransform(p, CGAffineTransformInvert(C.affineTransform));

    if (C.isGeometryFlipped) {
        CGAffineTransform flip = CGAffineTransformMakeScale(1.0f, -1.0f);
        flip = CGAffineTransformTranslate(flip, 0, C.bounds.size.height * (2.0f * C.anchorPoint.y - 1.0f));
        p = CGPointApplyAffineTransform(p, CGAffineTransformInvert(flip));
    }

    p.x -= txa;
    p.y -= tya;

    return p;
}

CGPoint pointFromChild(CALayer *C, CGPoint p) {

    CGFloat txb = - C.bounds.origin.x - C.bounds.size.width * C.anchorPoint.x;
    CGFloat tyb = - C.bounds.origin.y - C.bounds.size.height * C.anchorPoint.y;

    CGFloat txa = C.position.x;
    CGFloat tya = C.position.y;

    p.x += txb;
    p.y += tyb;

    if (C.isGeometryFlipped) {
        CGAffineTransform flip = CGAffineTransformMakeScale(1.0f, -1.0f);
        flip = CGAffineTransformTranslate(flip, 0, C.bounds.size.height * (2.0f * C.anchorPoint.y - 1.0f));
        p = CGPointApplyAffineTransform(p, flip);   
    }

    p = CGPointApplyAffineTransform(p, C.affineTransform);

    p.x += txa;
    p.y += tya;

    return p;
}