1

6 つの側面からなる立方体を構築します。各側面は CALayer であり、それぞれがサブビューとして (6) CATransformLayers (3D 変換を有効にするため) に追加されます。これらの 6 つの CATransformLayer は、サブビューとして単一の CATransformLayer に追加されます。

キューブ全体を 1 つのパッケージとして保持するこの単一の CATransformLayer を回転させると、すべてが機能し、アンカーポイントを 0,0 に設定し、アンカーポイント Z をキューブの中央に設定します。キューブはその中心を中心に完全に回転します。

問題: 現在の側面の 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 空間で正面の半分を覆っています。スクリーンショットを参照してください。

-(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];
}

回転後

私は一日中これにこだわっています。誰かが私を助けてくれることを願っています..!

4

1 に答える 1

0

You don't need to make a CATransformLayer for each layer, a single CATransformLayer to hold all layers is enough and you can make 3d transforms nevertheless as the CATransformLayer transforms apply on all anchors of the layers in it.

Why your rotation of the individual sides is off is because the anchorPoint of all sides is 0.5,0.5 (that is their respective center, so you rotate around that center)

You can go around this by translating the layer half its size in both desired directions while its being rotated albeit with a slight clipping initially , here is the osx code below, just change the NSColor etc to UIKit counterparts.

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"];
}
于 2013-11-06T12:58:40.337 に答える