上周开始学习贝塞尔曲线,其动机是因为买了Kitten-Yang的那本《A Guide To iOS Animation 2nd Edition》,于是也对动画和贝塞尔曲线产生了兴趣。在生活当中很多时候,我们都能见到贝塞尔曲线这个词,因为他从一开始在汽车车体工艺设计逐渐的发扬,最终又在计算机图形学领域占有重要的地位。关于贝塞尔曲线的发展和简单的原理,可以看《贝塞尔曲线扫盲》这篇文章来科普一下。
而在iOS开发中,由于在iOS 7.0之后扁平化UI设计中,由于省去了传统的iOS金属纹理、礼盒皮式的设计。这样,开发者就更加需要学习动画和绘矢量图的能力。下面我把这个动画的代码按照思路分析一下:
1.分析UI层次
在做一个动画样式之前,我们应该把作品的UI结构计划好。在这个动画中,我们需要准备两个圆形的Dot,因为在一个Dot在拖动离开原来位置的时候,为了模拟现实场景,原处应该也会保留一点印记。
在拖动过程中,我们在两个Dot的中间部分进行贝塞尔曲线的绘图,从而模拟“藕断丝连”的效果。
2.完成headDot的Pan手势(跟随)
接下来,我们考虑用户操作的角度。用户会拖动外层的headDot,这时候headDot的位置随着手指的拖动会跟随行动。而内层的trailDot会保持位置不变。我们对于headDot,增加一个UIPanGestureRecognizer
类型手势,即可达到效果。这里我们给出初始化即添加手势代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
- (instancetype) initWithFrame:(CGRect)frame { if (self = [super initWithFrame: frame]) { self.maxDistance = 180; self.shapLayer.frame = CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame)); self.headDot.center = self.center; self.trailDot.center = self.center; [self.layer addSublayer: self.shapLayer]; [self addSubview: self.trailDot]; [self addSubview: self.headDot]; // 注意加入顺序 UIPanGestureRecognizer *panGestrue = [[UIPanGestureRecognizer alloc] initWithTarget: self action: @selector(panHeadDot:)]; [self.headDot addGestureRecognizer: panGestrue]; } return self; } |
3.完成贝塞尔曲线闭合图形的绘制
那么说了半天贝塞尔曲线,这里终于用到了。在headDot随着我们手势拖动的同时,我们需要在两个圆中间绘制一个曲边矩形。如下图的蓝边内区域所示。在连接两个圆的圆心组成连心线RR'
,过两个圆心分别做垂线,得到AB
、DC
。连接AD
、BC
,取中点O
和P
,我们将其作为两条贝塞尔曲线的Control Point,对AD
、BC
进行绘制曲线,得到效果。
这里我们给出贝塞尔曲线闭合图形的绘制代码,其中公式全部由上图得来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#pragma mark - 绘制贝塞尔图形 - (void) reloadBeziePath { CGFloat r1 = self.trailDot.frame.size.width / 2.0f; CGFloat r2 = self.headDot.frame.size.width / 2.0f; CGFloat x1 = self.trailDot.center.x; CGFloat y1 = self.trailDot.center.y; CGFloat x2 = self.headDot.center.x; CGFloat y2 = self.headDot.center.y; CGFloat distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); CGFloat sinDegree = (x2 - x1) / distance; CGFloat cosDegree = (y2 - y1) / distance; CGPoint pointA = CGPointMake(x1 - r1 * cosDegree, y1 + r1 * sinDegree); CGPoint pointB = CGPointMake(x1 + r1 * cosDegree, y1 - r1 * sinDegree); CGPoint pointC = CGPointMake(x2 + r2 * cosDegree, y2 - r2 * sinDegree); CGPoint pointD = CGPointMake(x2 - r2 * cosDegree, y2 + r2 * sinDegree); CGPoint pointN = CGPointMake(p CGPoint pointN = CGPointMake(p S Animation 2nd Edition》,于是也对动画和贝塞尔曲线产生了兴趣。在生活当中很多时候,我们都能见到贝塞尔曲线这个词,因为他从一开始在汽车车体工艺设计逐渐的发扬,最终又在计算机图形学领域占有重要的地位。关于贝塞尔曲线的发展和简单的原理,可以看《贝塞尔曲线扫盲》这篇文章来科普一下。
而在iOS开发中,由于在iOS 7.0之后扁平化UI设计中,由于省去了传统的iOS金属纹理、礼盒皮式的设计。这样,开发者就更加需要学习动画和绘矢量图的能力。下面我把这个动画的代码按照思路分析一下: 1.分析UI层次在做一个动画样式之前,我们应该把作品的UI结构计划好。在这个动画中,我们需要准备两个圆形的Dot,因为在一个Dot在拖动离开原来位置的时候,为了模拟现实场景,原处应该也会保留一点印记。 在拖动过程中,我们在两个Dot的中间部分进行贝塞尔曲线的绘图,从而模拟“藕断丝连”的效果。 2.完成headDot的Pan手势(跟随)接下来,我们考虑用户操作的角度。用户会拖动外层的headDot,这时候headDot的位置随着手指的拖动会跟随行动。而内层的trailDot会保持位置不变。我们对于headDot,增加一个
3.完成贝塞尔曲线闭合图形的绘制那么说了半天贝塞尔曲线,这里终于用到了。在headDot随着我们手势拖动的同时,我们需要在两个圆中间绘制一个曲边矩形。如下图的蓝边内区域所示。在连接两个圆的圆心组成连心线 这里我们给出贝塞尔曲线闭合图形的绘制代码,其中公式全部由上图得来:
|