沿着anchorpoint旋转CATransformLayer

时间:2012-08-24 20:10:45

标签: iphone ios animation calayer caanimation

构建一个由6个边组成的立方体:每个边都是一个CALayer,然后将每个边作为子视图添加到(6)CATransformLayers(以启用3d变换)。 这6个CATransformLayers作为子视图添加到单个CATransformLayer。

当旋转这个将整个立方体保持为一个包的单个CATransformLayer时,一切正常,我将anchorpoint设置为0,0,将anchorpointZ设置为立方体的中间:立方体完全围绕其中心旋转。

问题: 我想“展开”当前侧面的4个相邻侧面,这意味着左侧,右侧,上方和下方的侧面朝向用户旋转90°但仍然坚持朝向用户的侧面。

为此,我举例说明当前一侧上方的锚点Z为0,锚点为(0.5,1),因此锚点基本上是公共边缘的中间位置。

设置多维数据集:

transformLayer = [CATransformLayer layer];
transformLayer.position = CGPointMake([UIScreen mainScreen].bounds.size.width/2,[UIScreen mainScreen].bounds.size.height/2);

CGRect layerRect = CGRectMake(0.0, 0.0, 150, 150); //frame rect for cube sides
CGPoint screenCenter = CGPointMake(self.transformLayer.bounds.size.width / 2, self.transformLayer.bounds.size.height / 2);

//side1
side1 = [CALayer layer];
side1.borderColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side1.backgroundColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side1.borderWidth = 2.0;
side1.cornerRadius = 30.0;
side1.frame = layerRect;
side1.position = screenCenter;


side1t = [CATransformLayer layer];
[side1t addSublayer:side1];


//side2
side2 = [CALayer layer];
side2.borderColor = [UIColor colorWithHue:0.25 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side2.backgroundColor = [UIColor colorWithHue:0.25 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side2.borderWidth = 2.0;
side2.cornerRadius = 30.0;    
side2.frame = layerRect;
side2.position = screenCenter;
//positioning
CATransform3D rotation = CATransform3DMakeRotation(M_PI/2, 0.0, 1.0, 0.0);
CATransform3D translation = CATransform3DMakeTranslation(150/2, 0.0, 150/-2 );
CATransform3D position = CATransform3DConcat(rotation, translation);
side2.transform = position;

side2t = [CATransformLayer layer];
[side2t addSublayer:side2];


//side3
side3 = [CALayer layer];
side3.borderColor = [UIColor colorWithHue:0.0 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side3.backgroundColor = [UIColor colorWithHue:0.0 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side3.borderWidth = 2.0;
side3.cornerRadius = 30.0;
side3.frame = layerRect;
side3.position = screenCenter;
//positioning
translation = CATransform3DMakeTranslation(0.0, 0.0, -150); //150
side3.transform = translation;

side3t = [CATransformLayer layer];
[side3t addSublayer:side3];


//side4
side4 = [CALayer layer];
side4.borderColor = [UIColor colorWithHue:0.2 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side4.backgroundColor = [UIColor colorWithHue:0.2 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side4.borderWidth = 2.0;
side4.cornerRadius = 30.0;
side4.frame = layerRect;
side4.position = screenCenter;
//positioning
rotation = CATransform3DMakeRotation(M_PI/2, 0.0, 1.0, 0.0);
translation = CATransform3DMakeTranslation(150/-2, 0.0, 150/-2);
side4.transform = CATransform3DConcat(rotation, translation);

side4t = [CATransformLayer layer];
[side4t addSublayer:side4];


//side5
side5 = [CALayer layer];
side5.borderColor = [UIColor colorWithHue:0.8 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side5.backgroundColor = [UIColor colorWithHue:0.8 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side5.borderWidth = 2.0;
side5.cornerRadius = 30.0;
side5.frame = layerRect;
side5.position = screenCenter;
//positioning
rotation = CATransform3DMakeRotation(M_PI/2, 1.0, .0, 0.0);
translation = CATransform3DMakeTranslation(0.0, 150/-2, 150/-2);
side5.transform = CATransform3DConcat(rotation, translation);

side5t = [CATransformLayer layer];
[side5t addSublayer:side5];


//side6
side6 = [CALayer layer];
side6.borderColor = [UIColor colorWithHue:0.0845 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
side6.backgroundColor = [UIColor colorWithHue:0.0845 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
side6.borderWidth = 2.0;
side6.cornerRadius = 30.0;
side6.frame = layerRect;
side6.position = screenCenter;
//positioning
rotation = CATransform3DMakeRotation(M_PI/2, 1.0, .0, 0.0);
translation = CATransform3DMakeTranslation(0.0, 150/2, 150/-2);
side6.transform = CATransform3DConcat(rotation, translation);

side6t = [CATransformLayer layer];
[side6t addSublayer:side6];


[self.transformLayer addSublayer:side1t];
[self.transformLayer addSublayer:side2t];
[self.transformLayer addSublayer:side3t];
[self.transformLayer addSublayer:side4t];
[self.transformLayer addSublayer:side5t];
[self.transformLayer addSublayer:side6t];

self.transformLayer.anchorPointZ = -150/2;
[self.layer addSublayer: transformLayer];

这部分不起作用。旋转(90°)是正确的,但是侧面最终处于完全错误的位置,在当前侧(z坐标)前面的一半立方体,并且在xy空间中覆盖正面的一半,请参见屏幕截图< / p>

-(void)unfoldUpperSide {
[CATransaction begin];
[CATransaction setAnimationDuration: 3.0];
side5t.anchorPoint = CGPointMake(0.5, 0);
side5t.anchorPointZ = 0;
side5t.transform = CATransform3DMakeRotation(-M_PI/2, 1, 0, 0);
[CATransaction commit];
}

after rotation

我整天坚持这一点,希望有人可以帮助我......!

1 个答案:

答案 0 :(得分:0)

您不需要为每个图层创建CATransformLayer,只需要一个CATransformLayer来保存所有图层就足够了,然后您可以进行3D变换,因为CATransformLayer变换适用于其中所有图层的所有锚点。

为什么单侧的旋转关闭是因为所有边的锚点都是0.5,0.5(这是它们各自的中心,所以你围绕那个中心旋转)

你可以通过在旋转时将其大小的一半转换为所需的方向来解决这个问题,尽管最初是轻微的剪裁,这里是下面的osx代码,只需将NSColor等更改为UIKit对应物。

enter image description here

-(void)cubeTest{

    float size = 100.0;

    CATransformLayer *transformLayer = [CATransformLayer layer];
    transformLayer.position = CGPointMake(cubeView.bounds.size.width/2,cubeView.bounds.size.height/2);

    CGRect layerRect = CGRectMake(0.0, 0.0, size, size); //frame rect for cube sides
    CGPoint screenCenter = CGPointMake(transformLayer.bounds.size.width / 2, transformLayer.bounds.size.height / 2);

    //side1
    CALayer *side1 = [CALayer layer];
    side1.borderColor = [NSColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side1.backgroundColor = [NSColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side1.borderWidth = 2.0;
    side1.cornerRadius = 30.0;
    side1.frame = layerRect;
    side1.position = screenCenter;
    [transformLayer addSublayer:side1];

    //side2
    CALayer *side2 = [CALayer layer];
    side2.borderColor = [NSColor colorWithHue:0.25 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side2.backgroundColor = [NSColor colorWithHue:0.25 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side2.borderWidth = 2.0;
    side2.cornerRadius = 30.0;
    side2.frame = layerRect;
    side2.position = screenCenter;
    //positioning
    CATransform3D rotation = CATransform3DMakeRotation(M_PI/2, 0.0, 1.0, 0.0);
    CATransform3D translation = CATransform3DMakeTranslation(size/2, 0.0, size/-2 );
    CATransform3D position = CATransform3DConcat(rotation, translation);
    side2.transform = position;
    [transformLayer addSublayer:side2];

    //side3
    CALayer *side3 = [CALayer layer];
    side3.borderColor = [NSColor colorWithHue:0.0 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side3.backgroundColor = [NSColor colorWithHue:0.0 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side3.borderWidth = 2.0;
    side3.cornerRadius = 30.0;
    side3.frame = layerRect;
    side3.position = screenCenter;
    //positioning
    translation = CATransform3DMakeTranslation(0.0, 0.0, -size); //size
    side3.transform = translation;
    [transformLayer addSublayer:side3];

    //side4
    CALayer *side4 = [CALayer layer];
    side4.borderColor = [NSColor colorWithHue:0.2 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side4.backgroundColor = [NSColor colorWithHue:0.2 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side4.borderWidth = 2.0;
    side4.cornerRadius = 30.0;
    side4.frame = layerRect;
    side4.position = screenCenter;
    //positioning
    rotation = CATransform3DMakeRotation(M_PI/2, 0.0, 1.0, 0.0);
    translation = CATransform3DMakeTranslation(size/-2, 0.0, size/-2);
    side4.transform = CATransform3DConcat(rotation, translation);
    [transformLayer addSublayer:side4];

    //side5
    CALayer *side5 = [CALayer layer];
    side5.borderColor = [NSColor colorWithHue:0.8 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side5.backgroundColor = [NSColor colorWithHue:0.8 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side5.borderWidth = 2.0;
    side5.cornerRadius = 30.0;
    side5.frame = layerRect;
    side5.position = screenCenter;
    //positioning
    rotation = CATransform3DMakeRotation(M_PI/2, 1.0, .0, 0.0);
    translation = CATransform3DMakeTranslation(0.0, size/-2, size/-2);
    side5.transform = CATransform3DConcat(rotation, translation);
    [transformLayer addSublayer:side5];

    //side6
    CALayer *side6 = [CALayer layer];
    side6.borderColor = [NSColor colorWithHue:0.0845 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    side6.backgroundColor = [NSColor colorWithHue:0.0845 saturation:1.0 brightness:1.0 alpha:0.8].CGColor;
    side6.borderWidth = 2.0;
    side6.cornerRadius = 30.0;
    side6.frame = layerRect;
    side6.position = screenCenter;
    //positioning
    rotation = CATransform3DMakeRotation(M_PI/2, 1.0, .0, 0.0);
    translation = CATransform3DMakeTranslation(0.0, size/2, size/-2);
    side6.transform = CATransform3DConcat(rotation, translation);
    [transformLayer addSublayer:side6];

    transformLayer.anchorPointZ = -size/2;
    [cubeView setWantsLayer:YES];
    [cubeView.layer addSublayer:transformLayer];

    //animate

    CGFloat perspective = -1.0/10000.0;
    CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];

    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = perspective;
    transformAnimation.fromValue = [NSValue valueWithCATransform3D:transform];

    transform.m34 = perspective;
    transform = CATransform3DRotate(transform, DEGREES_TO_RADIANS(90) , 1, 0, 0);

    transformAnimation.toValue = [NSValue valueWithCATransform3D:transform];

    transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    transformAnimation.repeatCount = INFINITY;
    transformAnimation.duration = 10.0;
    [transformLayer addAnimation:transformAnimation forKey:@"RotateTheBox"];

    [self sideAnimation:side1 transform:CATransform3DTranslate(CATransform3DRotate(side1.transform, DEGREES_TO_RADIANS(90) , 1, 0, 0), 0, size/2, size/2)];
    [self sideAnimation:side3 transform:CATransform3DTranslate(CATransform3DRotate(side3.transform, DEGREES_TO_RADIANS(-90) , 1, 0, 0), 0, size/2, -size/2)];
    [self sideAnimation:side2 transform:CATransform3DTranslate(CATransform3DRotate(side2.transform, DEGREES_TO_RADIANS(90) , 1, 0, 0), 0, size/2, size/2)];
    [self sideAnimation:side4 transform:CATransform3DTranslate(CATransform3DRotate(side4.transform, DEGREES_TO_RADIANS(-90) , 1, 0, 0), 0, size/2, -size/2)];
    [self sideAnimation:side6 transform:CATransform3DTranslate(side6.transform, 0, 0, size)];//lower cap

}

-(void)sideAnimation:(CALayer*)side transform:(CATransform3D)transform
{
    CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    transformAnimation.toValue = [NSValue valueWithCATransform3D:transform];
    transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    transformAnimation.repeatCount = INFINITY;
    transformAnimation.duration = 10.0;
    [side addAnimation:transformAnimation forKey:@"rotateSide"];
}