**第一次写博客有点激动呢**
使用 UIDynamic 的方法就不叙述了
这里先讲一下 牛顿摆是经过计算的一个公式才能达到理想状态 由于我不知道公式 所以做出来不能完美的达成 一个小球落下来另一个小球飞起来
接下来直接上代码 代码中的描述还是很详细的
#import "ViewController.h"
#import "ContentView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ContentView *view =[[ContentView alloc]initWithFrame:self.view.bounds];
view.backgroundColor=[UIColor blueColor];
[self.view addSubview:view];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#import "ContentView.h"
#import "BallsView.h"
@interface ContentView(){
UIDynamicAnimator *_animator;//仿真模拟器
NSMutableArray *_arrayBalls;
CGPoint _centers[100];//可变的小球中心坐标
UISnapBehavior *_snapB;
UIAttachmentBehavior *attachement1;
}
@end
static CGFloat radius=20;//小球半径
static CGFloat attachmentLenth=500;//链接长度
@implementation ContentView
-(id)initWithFrame:(CGRect)frame{
if (self=[super initWithFrame:frame]) {
//初始化仿真模拟器
_animator=[[UIDynamicAnimator alloc]initWithReferenceView:self];
//初始化所有仿真元素 就是小球
[self creatBalls];
//添加小球的行为元素
[self addBehavior];
//利用 drawRect 方法绘制小球和锚点的连线
//使用 touchBegan方法判断我们要抓住的小球 用 touchMove的方法使我们的小球随着手指滑动 使用 touchEnd 方法移除 snap 行为释放小球
}
return self;
}
static int b;
-(void)addBehavior{
//这样的方法要经常使用 可以避免程序的崩溃
if (!_arrayBalls.count) {
return;
}
//仿真元素的行为描述
UIDynamicItemBehavior *itemBehavior=[[UIDynamicItemBehavior alloc]initWithItems:_arrayBalls];
itemBehavior.elasticity=1.00001;//弹性
itemBehavior.resistance=.01;//阻尼
itemBehavior.density=1000;//密度
itemBehavior.allowsRotation=NO;//禁止旋转
[_animator addBehavior:itemBehavior];
//因为我们的小球都需要重力行为直接添加上就可以了
UIGravityBehavior *gravityB=[[UIGravityBehavior alloc]initWithItems:_arrayBalls];
gravityB.magnitude=10;//重力加速度
[_animator addBehavior:gravityB];
//添加碰撞行为
UICollisionBehavior *collisionB=[[UICollisionBehavior alloc]initWithItems:_arrayBalls];
[_animator addBehavior:collisionB];
//添加链接行为 链接行为是将两个点相连
for (int i=0; i<_arrayBalls.count; i++) {
UIAttachmentBehavior *attachmentB=[[UIAttachmentBehavior alloc]initWithItem:_arrayBalls[i] attachedToAnchor:_centers[i]];
attachmentB.length=attachmentLenth;
attachmentB.damping=0;
attachmentB.frequency=0;
[_animator addBehavior:attachmentB];
}
}
-(void)creatBalls{
_arrayBalls=[[NSMutableArray alloc]initWithCapacity:1];
//计算小球中心的坐标
for (int i=0; i<6; i++) {
CGPoint p=CGPointMake(60+i*2*radius+i*3, 30);
_centers[i]=p;
}
for (int i=0; i<6; i++) {
//这里创建一个小球的 view
BallsView *ball=[[BallsView alloc]initWithFrame:CGRectMake(0, 0, 2*radius, 2*radius) withRadius:radius];
//在这里确定小球的初始位置
ball.center=_centers[i];
//这里添加的 kvo 方法作用是当监听到小球的中心变化时 执行 setNeedDisplay 方法 走了这方法后 就会重新绘制contentView
[ball addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];
[self addSubview:ball];
[_arrayBalls addObject:ball];
}
}
- (void)drawRect:(CGRect)rect {
//绘图第一点 获取上下文
CGContextRef context=UIGraphicsGetCurrentContext();
//绘制连接线
for (int i=0; i<6; i++) {
UIView *view=_arrayBalls[i];
CGContextMoveToPoint(context, _centers[i].x, _centers[i].y);
CGContextAddLineToPoint(context,view.center.x, view.center.y);
}
CGContextStrokePath(context);
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
[self setNeedsDisplay];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch=[touches anyObject];
for (int i=0; i<6; i++) {
UIView *view=_arrayBalls[i];
CGPoint point=[touch locationInView:view];
if ([view pointInside:point withEvent:nil]) {
//NSLog(@"%d",i);
b=i;
}
}
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if (_snapB==nil) {
UITouch *touch=[touches anyObject];
CGPoint point=[touch locationInView:self];
_snapB=[[UISnapBehavior alloc]initWithItem:_arrayBalls[b] snapToPoint:point];
//NSLog(@"%d",b);
[_animator addBehavior:_snapB];
}else{
[_animator removeBehavior:_snapB];
_snapB=nil;
}
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[_animator removeBehavior:_snapB];
}
@end
#import <UIKit/UIKit.h>
@interface BallsView : UIView
-(id)initWithFrame:(CGRect)frame withRadius:(CGFloat)radius;
@end
#import "BallsView.h"
@implementation BallsView
-(id)initWithFrame:(CGRect)frame withRadius:(CGFloat)radius{
if (self =[super initWithFrame:frame]) {
//初始化小球的属性
self.layer.cornerRadius=radius;
self.layer.borderColor=[UIColor greenColor].CGColor;
self.layer.borderWidth=2;
self.backgroundColor=[UIColor yellowColor];
self.layer.shadowColor=[UIColor blackColor].CGColor;
self.layer.shadowRadius=.5;
}
return self;
}
@end