我有一组垂直排列的瓷砖。它们意味着围绕X轴旋转。想想手风琴。我希望每个tile n + 1始终挂起tile n。
在最后两个屏幕截图中,青色瓷砖应该贴在黄色瓷砖上。它不是。 我不懂为什么。更不用说了,为什么当我旋转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一样。
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中,然后我将其添加为 previous 行的子层,目的是让每个CATransformLayer影响其每个子层。< / p>
[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);
我明白了:
我有read and re-read Apple's documentation,密切关注此事:
锚点影响几何操作
几何相关 层的操作相对于该层的锚点发生, 您可以使用图层的anchorPoint属性访问它。该 操纵时,锚点的影响最明显 位置或变换图层的属性。 位置属性 总是相对于图层的锚点指定,任何 应用于图层的变换相对于锚点发生 也是如此。
(强调我的)
可以公平地说,我现在完全糊涂了。任何人都可以看到/解释我做错了什么?
如何安排这些图层,使我的图块始终相邻,从上到下?
这是图层层次结构的转储:
<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}
答案 0 :(得分: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) ;
} ;
现在对于作为根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
}
现在我只需摆脱那些愚蠢的颜色,对边缘进行抗锯齿并提供一些阴影渐变层,并观察那令我讨厌的视角(最后一行&#34;灰色&#34;太高)更多调整使用m34和/或baseLayer中心[anchorPoint / position]。
将角度和系数替换为:
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 ;
我们现在得到: