iOS 使用 CGAffineTransform Make Translation 从一个视图的中心到另一个视图的中心绘制虚线动画第二个视图
iOS draw dotted line from one view's center to another view's center animating second view using CGAffineTransformMakeTranslationg
我正在尝试构建一些具有挑战性的东西。
基本上,我在这里得到了这个场景:
由于这个 Whosebug 的回答,我能够画出虚线:
Draw dotted (not dashed!) line, with IBDesignable in 2017
虚线画在里面:
-(void)drawRect:(CGRect)rect
{
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo1.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo2.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo3.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo4.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo5.center];
}
-(void)drawDottedLineFromStartingPoint:(CGPoint)startPoint ToEndPoint:(CGPoint)endPoint
{
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:startPoint];
[path addLineToPoint:endPoint];
path.lineWidth = 4;
CGFloat dashes[] = {path.lineWidth * 0, path.lineWidth * 2};
[path setLineDash:dashes count:2 phase:0];
path.lineCapStyle = kCGLineCapRound;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(ctx, [ThemeManager mediumTextColor].CGColor);
[path stroke];
}
我面临的问题是每个较小的圆圈都通过落入到位而动画化。
我制作小圆圈动画的方法是使用类似的东西:
CGAffineTransformMakeTranslation(0, 50);
当我这样做时,虚线是从大圆圈到小圆圈的最终静止位置绘制的,虚线不会 "follow" 小圆圈正在动画并掉落.
所以你看到的是这样的:
对于我想要实现的目标,有什么简单的解决方案吗?我试过考虑使用 NSTimer 并计算斜边长度,除以持续时间,但我没有走得太远:D
我前一段时间做了一个应用程序,它做了一些类似于你想要的事情,所以我修改了它来做你想做的事情。我有一个名为 NodeView 的 class,它只是一个 UIView subclass 和一个名为 line 的 属性,它是一个 UIBezierPath(你可以用 subclass UIImageView 做同样的事情事物)。我使用计时器来移动节点,并观察节点的中心 属性,这样我就可以调用 drawRect 来描边节点的线。这个版本一个一个地移动节点。我将控制器的视图设置为 UIView 的子 class,这是该子class、
中的代码
#import "RDView.h"
#import "NodeView.h"
@interface RDView ()
@property (weak, nonatomic) IBOutlet UIView *bigView; // this is equivalent to your large image view from which the other image views drop
@property (strong,nonatomic) NSMutableArray *paths;
@end
@implementation RDView
-(void)didMoveToWindow {
self.bigView.layer.cornerRadius = self.bigView.frame.size.width/2.0;
self.paths = [NSMutableArray new];
self.nodes = [NSMutableArray new];
for (int i = 0; i<5; i++) {
NodeView *aNode = [NodeView new];
CGFloat hue = arc4random_uniform(1000)/1000.0;
aNode.backgroundColor = [UIColor colorWithHue:hue saturation:1 brightness:1 alpha:1.0];
aNode.frame = CGRectMake(0, 0, 40, 40);
[self.bigView layoutIfNeeded];
aNode.center = self.bigView.center;
[self addSubview:aNode];
[self.nodes addObject:aNode];
aNode.line = [UIBezierPath bezierPath];
CGFloat dashes[] = {0, aNode.line.lineWidth * 4};
[aNode.line setLineDash:dashes count:2 phase:0];
aNode.line.lineCapStyle = kCGLineCapRound;
[aNode.line moveToPoint:[self.bigView center]];
}
[self bringSubviewToFront:self.bigView];
for (NodeView *aNode in self.nodes) {
[aNode addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];
}
[self performSelector:@selector(dropNodes) withObject:nil afterDelay:1];
}
-(void)dropNodes {
static int i = 0;
[NSTimer scheduledTimerWithTimeInterval:.005 target:self selector:@selector(dropNode:) userInfo:@{@"nodeIndex":@(i)} repeats:YES];
i++;
}
-(void)dropNode:(NSTimer *) timer {
NSInteger i = [timer.userInfo[@"nodeIndex"] integerValue];
NodeView *node = self.nodes[i];
[node setCenter: CGPointMake(node.center.x + (i-2)*.25, node.center.y + 1)]; // spread the nodes out horizontally and move down
[node.line addLineToPoint:node.center];
if (node.center.y > 400) {
[timer invalidate];
if (i < self.nodes.count-1) {
[self dropNodes];
}
}
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"center"] ) {
[self setNeedsDisplay];
}
}
- (void)drawRect:(CGRect)rect {
for (NodeView *aNode in self.nodes) {
[aNode.line stroke];
}
}
你可以在这里找到我的项目 link,http://jmp.sh/lIl5MXp
我要感谢 rdelmar 启发了我以及这个 link 告诉我一个视图的 presentationLayer frame
ios observing change in frame of a UIView during animation
在这种情况下我没有使用 KVO,但我确实使用 NSTimer 和重绘屏幕解决了我的问题。
基本上我在为圆圈掉落的动画开始后,我还安排了一个每 0.01 秒触发一次的 NSTimer,回调方法检查最后的圆圈照片是否已完成动画,如果是,则使计时器无效:
-(void)showIntroAnimations
{
self.hasBegunAnimating = YES;
// start animating circle photos falling down
[self setupObservers];
}
-(void)setupObservers
{
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(redrawLines:) userInfo:nil repeats:YES];
}
-(void)redrawLines:(NSTimer *)timer
{
if([self.photo5.layer animationKeys].count > 0)
{
[self setNeedsDisplay];
}
else
{
[timer invalidate];
timer = nil;
}
}
我正在尝试构建一些具有挑战性的东西。
基本上,我在这里得到了这个场景:
由于这个 Whosebug 的回答,我能够画出虚线:
Draw dotted (not dashed!) line, with IBDesignable in 2017
虚线画在里面:
-(void)drawRect:(CGRect)rect
{
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo1.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo2.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo3.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo4.center];
[self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo5.center];
}
-(void)drawDottedLineFromStartingPoint:(CGPoint)startPoint ToEndPoint:(CGPoint)endPoint
{
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:startPoint];
[path addLineToPoint:endPoint];
path.lineWidth = 4;
CGFloat dashes[] = {path.lineWidth * 0, path.lineWidth * 2};
[path setLineDash:dashes count:2 phase:0];
path.lineCapStyle = kCGLineCapRound;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(ctx, [ThemeManager mediumTextColor].CGColor);
[path stroke];
}
我面临的问题是每个较小的圆圈都通过落入到位而动画化。
我制作小圆圈动画的方法是使用类似的东西:
CGAffineTransformMakeTranslation(0, 50);
当我这样做时,虚线是从大圆圈到小圆圈的最终静止位置绘制的,虚线不会 "follow" 小圆圈正在动画并掉落.
所以你看到的是这样的:
对于我想要实现的目标,有什么简单的解决方案吗?我试过考虑使用 NSTimer 并计算斜边长度,除以持续时间,但我没有走得太远:D
我前一段时间做了一个应用程序,它做了一些类似于你想要的事情,所以我修改了它来做你想做的事情。我有一个名为 NodeView 的 class,它只是一个 UIView subclass 和一个名为 line 的 属性,它是一个 UIBezierPath(你可以用 subclass UIImageView 做同样的事情事物)。我使用计时器来移动节点,并观察节点的中心 属性,这样我就可以调用 drawRect 来描边节点的线。这个版本一个一个地移动节点。我将控制器的视图设置为 UIView 的子 class,这是该子class、
中的代码#import "RDView.h"
#import "NodeView.h"
@interface RDView ()
@property (weak, nonatomic) IBOutlet UIView *bigView; // this is equivalent to your large image view from which the other image views drop
@property (strong,nonatomic) NSMutableArray *paths;
@end
@implementation RDView
-(void)didMoveToWindow {
self.bigView.layer.cornerRadius = self.bigView.frame.size.width/2.0;
self.paths = [NSMutableArray new];
self.nodes = [NSMutableArray new];
for (int i = 0; i<5; i++) {
NodeView *aNode = [NodeView new];
CGFloat hue = arc4random_uniform(1000)/1000.0;
aNode.backgroundColor = [UIColor colorWithHue:hue saturation:1 brightness:1 alpha:1.0];
aNode.frame = CGRectMake(0, 0, 40, 40);
[self.bigView layoutIfNeeded];
aNode.center = self.bigView.center;
[self addSubview:aNode];
[self.nodes addObject:aNode];
aNode.line = [UIBezierPath bezierPath];
CGFloat dashes[] = {0, aNode.line.lineWidth * 4};
[aNode.line setLineDash:dashes count:2 phase:0];
aNode.line.lineCapStyle = kCGLineCapRound;
[aNode.line moveToPoint:[self.bigView center]];
}
[self bringSubviewToFront:self.bigView];
for (NodeView *aNode in self.nodes) {
[aNode addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];
}
[self performSelector:@selector(dropNodes) withObject:nil afterDelay:1];
}
-(void)dropNodes {
static int i = 0;
[NSTimer scheduledTimerWithTimeInterval:.005 target:self selector:@selector(dropNode:) userInfo:@{@"nodeIndex":@(i)} repeats:YES];
i++;
}
-(void)dropNode:(NSTimer *) timer {
NSInteger i = [timer.userInfo[@"nodeIndex"] integerValue];
NodeView *node = self.nodes[i];
[node setCenter: CGPointMake(node.center.x + (i-2)*.25, node.center.y + 1)]; // spread the nodes out horizontally and move down
[node.line addLineToPoint:node.center];
if (node.center.y > 400) {
[timer invalidate];
if (i < self.nodes.count-1) {
[self dropNodes];
}
}
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"center"] ) {
[self setNeedsDisplay];
}
}
- (void)drawRect:(CGRect)rect {
for (NodeView *aNode in self.nodes) {
[aNode.line stroke];
}
}
你可以在这里找到我的项目 link,http://jmp.sh/lIl5MXp
我要感谢 rdelmar 启发了我以及这个 link 告诉我一个视图的 presentationLayer frame
ios observing change in frame of a UIView during animation
在这种情况下我没有使用 KVO,但我确实使用 NSTimer 和重绘屏幕解决了我的问题。
基本上我在为圆圈掉落的动画开始后,我还安排了一个每 0.01 秒触发一次的 NSTimer,回调方法检查最后的圆圈照片是否已完成动画,如果是,则使计时器无效:
-(void)showIntroAnimations
{
self.hasBegunAnimating = YES;
// start animating circle photos falling down
[self setupObservers];
}
-(void)setupObservers
{
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(redrawLines:) userInfo:nil repeats:YES];
}
-(void)redrawLines:(NSTimer *)timer
{
if([self.photo5.layer animationKeys].count > 0)
{
[self setNeedsDisplay];
}
else
{
[timer invalidate];
timer = nil;
}
}