iOS developeriOS的高大上魔法🔮学习重力学

iOS UIKit动力学(三)碰撞(UICollisionBeh

2016-11-07  本文已影响755人  JerryLMJ

iOS UIKit力学(一)基本介绍(目录)

构造

UICollisionBehavior * collisionBehavior = 
[[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];

设置碰撞边界

UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

这是将重力向量设置为{1, 1}后,_dynamicItem1ViewReference View边界碰撞产生的效果。
translatesReferenceBoundsIntoBoundary属性表示是否以当前坐标系边界作为检测碰撞的边界。此时_dynamicItem1View运动到self.view的边界时就会发生碰撞。

碰撞的类型

@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
    // 元素之间的碰撞
    UICollisionBehaviorModeItems        = 1 << 0,
    // 边界碰撞
    UICollisionBehaviorModeBoundaries   = 1 << 1,
    // 碰撞所有
    UICollisionBehaviorModeEverything   = NSUIntegerMax
} NS_ENUM_AVAILABLE_IOS(7_0);
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeItems;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

collisionMode属性为UICollisionBehaviorModeItems时,碰撞只发生在元素与元素之间,即使将translatesReferenceBoundsIntoBoundary属性设置为YES也不会检测边界碰撞。
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeBoundaries;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

collisionMode属性为UICollisionBehaviorModeBoundaries时,运动元素只检测是否与边界发生碰撞,而不会检测是否与其他元素进行碰撞。
这里我们将translatesReferenceBoundsIntoBoundary设置为YES,发现蓝球与Reference View边界发生了碰撞。
如果translatesReferenceBoundsIntoBoundaryNO又会怎样呢?

可以看出蓝球并没有与边界发生碰撞,这并不是因为collisionMode属性没有生效,而是因为当translatesReferenceBoundsIntoBoundaryNO时,就没有需要检测碰撞的边界了,所以蓝球因没有边界的阻挡会一直运动下去。
所以translatesReferenceBoundsIntoBoundary属性只负责碰撞边界的设置,并不会影响碰撞的类型。
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

碰撞边界内边距

UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
collisionBehavior.translatesReferenceBoundsIntoBoundary = NO;
[collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(50, 50, 50, 50)];
[_animator addBehavior:collisionBehavior];

setTranslatesReferenceBoundsIntoBoundaryWithInsets:函数是用来设置碰撞Reference View边界的内边距的。


通过效果可以看出,碰撞边界的上下左右分别向内收缩了50像素的距离。这里的translatesReferenceBoundsIntoBoundary属性被设置为NO,但是碰撞边界依然是有的,也就是说setTranslatesReferenceBoundsIntoBoundaryWithInsets:函数和translatesReferenceBoundsIntoBoundary属性设置的边界是相互独立的,两者之间没有联系。

自定义碰撞边界

-(void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath *)bezierPath;
// 创建椭圆形路径对象
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 500)];
path.lineWidth     = 1.f;
path.lineCapStyle  = kCGLineCapRound;
path.lineJoinStyle = kCGLineCapRound;
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
[collisionBehavior addBoundaryWithIdentifier:@"path1" forPath:path];
[_animator addBehavior:collisionBehavior];

有关UIBezierPath请看:UIBezierPath介绍
-(void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
[collisionBehavior addBoundaryWithIdentifier:@"path2" fromPoint:CGPointMake(350, 100) toPoint:CGPointMake(150, 500)];
[_animator addBehavior:collisionBehavior];

效果中的红色边界线实际是看不到的,这里是为了效果格外添加上的。

// 根据获取指定已命名的碰撞边界的贝塞尔曲线
-(nullable UIBezierPath *)boundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除指定已命名的碰撞边界
-(void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
// 获得所有命名
@property (nullable, nonatomic, readonly, copy) NSArray<id <NSCopying>> *boundaryIdentifiers;
// 移除所有添加的碰撞边界
-(void)removeAllBoundaries;

代理方法

@protocol UICollisionBehaviorDelegate <NSObject>
@optional
// 当一个两个动态元素之间发生碰撞时调用
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
// 当一个两个动态元素之间碰撞结束时调用
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

// 当一个动态元素与边界发生碰撞时调用
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier atPoint:(CGPoint)p;
// 当一个动态元素与边界碰撞结束时调用
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier;
@end

版权声明:出自MajorLMJ技术博客的原创作品 ,转载时必须注明出处及相应链接!

上一篇下一篇

猜你喜欢

热点阅读