1

私は縦に並べられたタイルのセットを持っています。これらは、X 軸を中心に回転することを意図しています。アコーディオンを考えてみてください。各タイル n+1 が常にタイル n にぶら下がっているようにします。

最後の 2 つのスクリーン ショットのシアンのタイルは、黄色のタイルに接続する必要があります。そうではない。私はなぜなのか理解していない。さらに言えば、row0 を回転させると、次の 5 つのタイルがすべて回転されるのはなぜですか (これが私が望むことです)。 3番目と4番目のタイル。

参考までに、設定は次のとおりです。

 CGRect  tileRect  = (CGRect)  {CGPointZero, {self.bounds.size.width, 30.0f}} ;
 CGRect  pageRect  = tileRect ;    pageRect.size.height *= 3 ;
 CGPoint baseCenter= (CGPoint) {self.bounds.size.width / 2.0f, 0} ;

 CGPoint anchorMidTop=   (CGPoint) {0.5f, 0.0f} ;
 CGPoint anchorTopLeft=  (CGPoint) {0.0f, 0.0f} ;

 CGPoint positionNW  =   (CGPoint) {0.0f, 0.0f} ;

 CALayer * (^setupLayerGeometry)(CALayer *, CGRect, CGPoint, CGPoint) =
 ^(CALayer * layer, CGRect b, CGPoint a, CGPoint p) {
     layer.bounds = b ;
     layer.anchorPoint = a ;
     layer.position = p ;
     return layer ;
 } ;

 CALayer * (^setupColor)(CALayer *, UIColor *) = ^(CALayer * layer, UIColor * color) {
     layer.backgroundColor = color.CGColor ;
     layer.opacity = 0.850f ;
     return layer ;
 } ;

 CALayer * (^stdLayer)(UIColor *, CGPoint, CGPoint) =
 ^CALayer * (UIColor * color, CGPoint anchor, CGPoint pos) {
     return setupLayerGeometry(
         setupColor([CALayer layer], color)
         ,   tileRect
         ,   anchor
         ,   pos) ;
 } ; 

 CATransformLayer * (^transformLayer)(CGRect, CGPoint, CGPoint) =
 ^CATransformLayer * (CGRect bounds, CGPoint anchor, CGPoint pos) {
     return (CATransformLayer *) setupLayerGeometry([CATransformLayer layer]
     ,   bounds
     ,   anchor
     ,   pos) ;
 } ;

 self.baseLayer = transformLayer(tileRect,    anchorTopLeft, baseCenter) ;

 CATransform3D initialTransform = self.baseLayer.sublayerTransform ;
 initialTransform.m34 = 1.0f / -200.0f ;
 self.baseLayer.sublayerTransform = initialTransform ;
 [self.layer addSublayer:self.baseLayer] ;

 CALayer * (^wrap0) (CALayer *) = ^CALayer * (CALayer * layer) {
     CALayer * wrap = transformLayer(tileRect,    anchorTopLeft, positionNW) ;
     [wrap addSublayer:layer] ;
     return wrap ;
 } ;

 CALayer * (^wrap)(CALayer *) = wrap0 ;

現在、プレーンな CALayer のように 6 つのタイルを作成しています。

 CALayer * row0  = stdLayer([UIColor redColor],      anchorMidTop, (CGPoint) {0, 0}) ;
 CALayer * row1  = stdLayer([UIColor blueColor],     anchorMidTop, (CGPoint) {0, 30}) ;
 CALayer * row2  = stdLayer([UIColor yellowColor],   anchorMidTop, (CGPoint) {0, 60}) ;
 CALayer * row3  = stdLayer([UIColor cyanColor],     anchorMidTop, (CGPoint) {0, 90}) ;
 CALayer * row4  = stdLayer([UIColor purpleColor],   anchorMidTop, (CGPoint) {0, 120}) ;
 CALayer * row5  = stdLayer([UIColor magentaColor],  anchorMidTop, (CGPoint) {0, 150}) ;

ここで、そのような各タイルを親 CATransformLayer にラップし、それをの行のサブレイヤーとして追加します。これは、各 CATransformLayer がそのサブレイヤーに影響を与えるようにするためです。

 [self.baseLayer  addSublayer:wrap(row0)] ;
 [row0.superlayer addSublayer:wrap(row1)] ;
 [row1.superlayer addSublayer:wrap(row2)] ;
 [row2.superlayer addSublayer:wrap(row3)] ;
 [row3.superlayer addSublayer:wrap(row4)] ;
 [row4.superlayer addSublayer:wrap(row5)] ;

 CGFloat angle = M_PI / 10.0f ;

 row0.superlayer.sublayerTransform = CATransform3DMakeRotation(-angle, 1, 0, 0);

この時点で、次のようになります。

ここに画像の説明を入力

そして、最後の行を次のように置き換えるまで、それを釘付けにしたと思いました:

 row3.superlayer.sublayerTransform = CATransform3DMakeRotation(-angle, 1, 0, 0);

そして、ここに私が得るものがあります:

ここに画像の説明を入力

代わりに、上記の行を次のように置き換えます。

 row0.superlayer.sublayerTransform = CATransform3DMakeRotation(-angle, 1, 0, 0);
 row3.superlayer.sublayerTransform = CATransform3DMakeRotation( angle, 1, 0, 0);

私はこれを得る:

ここに画像の説明を入力

これに細心の注意を払いながら、 Appleのドキュメントを読んで再読しました:

アンカー ポイントが幾何学的操作に影響を与える

レイヤーのジオメトリ関連の操作は、そのレイヤーのアンカー ポイントに関連して発生します。これには、レイヤーの anchorPoint プロパティを使用してアクセスできます。アンカー ポイントの影響は、レイヤーの位置または変換プロパティを操作するときに最も顕著になります。position プロパティは常にレイヤーのアンカー ポイントを基準にして指定され、レイヤーに適用する変換もアンカー ポイントを基準にして行われます。

(私のものを強調)

私は今、完全に混乱していると言っても過言ではありません。誰でも私が間違っていることを確認/説明できますか?

タイルが常に上から下に隣接するようにこれらのレイヤーを配置するにはどうすればよいですか?

レイヤー階層のダンプは次のとおりです。

 <CATransformLayer> frame: {{100, 0}, {200, 30}} pos: {100, 0} anchor: {0, 0}
   <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 0}
     <CALayer> frame: {{-100, 0}, {200, 30}} pos: {0, 0} anchor: {0.5, 0}
     <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 0}
       <CALayer> frame: {{-100, 30}, {200, 30}} pos: {0, 30} anchor: {0.5, 0}
       <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 0}
         <CALayer> frame: {{-100, 60}, {200, 30}} pos: {0, 60} anchor: {0.5, 0}
         <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 0}
           <CALayer> frame: {{-100, 90}, {200, 30}} pos: {0, 90} anchor: {0.5, 0}
           <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 0}
             <CALayer> frame: {{-100, 120}, {200, 30}} pos: {0, 120} anchor: {0.5, 
             <CATransformLayer> frame: {{0, 0}, {200, 30}} pos: {0, 0} anchor: {0, 
               <CALayer> frame: {{-100, 150}, {200, 30}} pos: {0, 150} anchor: {0.5, 0}
4

1 に答える 1

0

わかった。ついに!

ここに画像の説明を入力

コードは次のとおりです。

- (void) reloadData {
    for (CALayer * layer in [self.baseLayer.sublayers copy]) {
        [layer removeFromSuperlayer] ;
    }

    CGRect  tileRect  = (CGRect)  {CGPointZero, {self.bounds.size.width, 30.0f}} ;
    CGFloat halfWidth = self.bounds.size.width / 2.0f ;

ヘルパー ブロック:

    CALayer * (^setupLayerGeometry)(CALayer *, CGRect, CGPoint, CGPoint, NSString *) =
    ^(CALayer * layer, CGRect b, CGPoint a, CGPoint p, NSString * n) {
        layer.bounds = b ;
        layer.anchorPoint = a ;
        layer.position = p ;
        layer.name = n ;
        return layer ;
    } ;

    CALayer * (^setupColor)(CALayer *, UIColor *) = ^(CALayer * layer, UIColor * color) {
        layer.backgroundColor = color.CGColor ;
        layer.opacity = 0.850f ;
        return layer ;
    } ;

    CALayer * (^stdLayer)(UIColor *, CGPoint, CGPoint, NSString *) =
    ^CALayer * (UIColor * color, CGPoint anchor, CGPoint pos, NSString * n) {
        return setupLayerGeometry(
            setupColor([CALayer layer], color)
        ,   tileRect
        ,   anchor
        ,   pos
        ,   n) ;
    } ;

    CATransformLayer * (^transformLayer)(CGRect, CGPoint, CGPoint, NSString *) =
    ^CATransformLayer * (CGRect bounds, CGPoint anchor, CGPoint pos, NSString * n) {
        return (CATransformLayer *) setupLayerGeometry(
            [CATransformLayer layer]
            ,   bounds
            ,   anchor
            ,   pos
            ,   n) ;
    } ;

次に、ルートである baseLayer についてCATransformLayer

#define ANC(x,y)    (CGPoint) {x, y}
#define POS(x,y)    (CGPoint) {x, y}

    [self.baseLayer removeFromSuperlayer] ;
    self.baseLayer = transformLayer(tileRect,    ANC(0, 0), POS(halfWidth, 0), @"baseLayer") ;

CATransformLayer次の行のスーパー レイヤーとしても機能するルートとして各行を作成します。

    CALayer * row0  = stdLayer([UIColor redColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row0") ;
    CATransformLayer * trn0 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 0), @"trn0") ;
    [self.baseLayer addSublayer:trn0] ;
    [trn0 addSublayer:row0] ;


    CALayer * row1  = stdLayer([UIColor blueColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row1") ;
    CATransformLayer * trn1 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn1") ;
    [trn1 addSublayer:row1] ;
    [trn0 addSublayer:trn1] ;

    CALayer * row2  = stdLayer([UIColor yellowColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row2") ;
    CATransformLayer * trn2 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn2") ;
    [trn2 addSublayer:row2] ;
    [trn1 addSublayer:trn2] ;

    CALayer * row3  = stdLayer([UIColor cyanColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row3") ;
    CATransformLayer * trn3 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn3") ;
    [trn3 addSublayer:row3] ;
    [trn2 addSublayer:trn3] ;

    CALayer * row4  = stdLayer([UIColor purpleColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row4") ;
    CATransformLayer * trn4 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn4") ;
    [trn4 addSublayer:row4] ;
    [trn3 addSublayer:trn4] ;

    CALayer * row5  = stdLayer([UIColor magentaColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row5") ;
    CATransformLayer * trn5 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn5") ;
    [trn5 addSublayer:row5] ;
    [trn4 addSublayer:trn5] ;

    CALayer * row6  = stdLayer([UIColor lightGrayColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row6") ;
    CATransformLayer * trn6 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn6") ;
    [trn6 addSublayer:row6] ;
    [trn5 addSublayer:trn6] ;

    CALayer * row7  = stdLayer([UIColor darkGrayColor],      ANC(0.0, 0.0), POS(-halfWidth, 0), @"row7") ;
    CATransformLayer * trn7 = (CATransformLayer *) transformLayer(tileRect,    ANC(0, 0), POS(0, 30), @"trn7") ;
    [trn7 addSublayer:row7] ;
    [trn6 addSublayer:trn7] ;

最後にトランスフォームを設定します。各行は次の行の親であるため (埋め込まれた のおかげでCATransformLayer)、必要な角度は直接の親に対して相対的であり、特定のタイルが表示される行番号とは無関係です。

    CGFloat angle = M_PI / 10.0f ;

    trn0.sublayerTransform =  CATransform3DMakeRotation(1.0*angle, 1, 0, 0);
    trn1.sublayerTransform =  CATransform3DMakeRotation(-1.0*angle, 1, 0, 0);
    trn2.sublayerTransform =  CATransform3DMakeRotation(-1.0*angle, 1, 0, 0);
    trn3.sublayerTransform =  CATransform3DMakeRotation(1.0*angle, 1, 0, 0);
    trn4.sublayerTransform =  CATransform3DMakeRotation(1.0*angle, 1, 0, 0);
    trn5.sublayerTransform =  CATransform3DMakeRotation(-1.0*angle, 1, 0, 0);
    trn6.sublayerTransform =  CATransform3DMakeRotation(-1.0*angle, 1, 0, 0);
    trn7.sublayerTransform =  CATransform3DMakeRotation(2.0*angle, 1, 0, 0);

    CATransform3D initialTransform = self.baseLayer.sublayerTransform ;
    initialTransform.m34 = 1.0f / -200.0f ;
    self.baseLayer.sublayerTransform = initialTransform ;

    [self.layer addSublayer:self.baseLayer] ;

#undef ANC
#undef POS

}

今、私はそれらの愚かな色を取り除き、エッジをアンチエイリアスし、いくつかの影のグラデーションレイヤーを提供し、私を悩ませているその遠近感を観察する必要があります(最後の行の「灰色」は高すぎます)m34および/またはbaseLayerセンターでさらに微調整する[アンカーポイント/位置]。

角度と係数を次のように置き換えます。

    CGFloat angle = M_PI / 3.0f ;

    trn0.sublayerTransform =  CATransform3DMakeRotation(-1.0*angle, 1, 0, 0);
    trn1.sublayerTransform =  CATransform3DMakeRotation(2.0*angle, 1, 0, 0);
    trn2.sublayerTransform =  CATransform3DMakeRotation(-2.0*angle, 1, 0, 0);
    trn3.sublayerTransform =  CATransform3DMakeRotation(2.0*angle, 1, 0, 0);
    trn4.sublayerTransform =  CATransform3DMakeRotation(-2.0*angle, 1, 0, 0);
    trn5.sublayerTransform =  CATransform3DMakeRotation(2.0*angle, 1, 0, 0);
    trn6.sublayerTransform =  CATransform3DMakeRotation(-2.0*angle, 1, 0, 0);
    trn7.sublayerTransform =  CATransform3DMakeRotation(2.0*angle, 1, 0, 0);

そして、次の視点:

    initialTransform.m34 = 1.0f / -400.0f ;

次のようになります。

ここに画像の説明を入力

于 2014-04-13T20:29:10.143 に答える