飘动心形的简单动画

今天做了一个点击按钮飘动心形的简单动画,效果如下:

gifAnimate.gif

每点击一下按钮,就生成一个心形,并执行飘动的动画。封装heartView主要就两件事:1.画一个心形 2.执行动画

  • 画心形思路:左边一个弧度-接着左边一个半圆-接着右边一个半圆-最后右边一个弧度闭合,代码如下:
//画图 需要在自带的drawRect方法中操作
- (void)drawRect:(CGRect)rect
{
    //设置颜色
    [_strokeColor setStroke];
    [_fillColor setFill];
    
    CGFloat drawingPadding = 4.0;
    //❤️上面的圆的半径 宽度减去两边空隙除以4
    CGFloat curveRadius = floor((CGRectGetWidth(rect) - 2*drawingPadding) / 4.0);
    
    //创建路径
    UIBezierPath *heartPath = [UIBezierPath bezierPath];
    
    //以💖的底部顶点为基点 顺时针画:弧度-半圆-半圆-弧度连接基点
    
    //1.移动到💖的底部顶点
    CGPoint bottomLocation = CGPointMake(floor(CGRectGetWidth(rect) / 2.0), CGRectGetHeight(rect) - drawingPadding);
    [heartPath moveToPoint:bottomLocation];
    
    //2.画左边的弧形 贝赛尔曲线
    //endpoint x:4 y:高度一半以上一点
    CGPoint endPintLeftCurve = CGPointMake(drawingPadding, floor(CGRectGetHeight(rect) / 2.4));
    [heartPath addQuadCurveToPoint:endPintLeftCurve controlPoint:CGPointMake(endPintLeftCurve.x, endPintLeftCurve.y + curveRadius)];
    
    //3.画左边的半圆 startAngle:起始的弧度(PI3.14为180度 2PI为360度) endAngle:圆弧结束的弧度 clockwise:YES为顺时针,No为逆时针
    [heartPath addArcWithCenter:CGPointMake(endPintLeftCurve.x + curveRadius, endPintLeftCurve.y) radius:curveRadius startAngle:PI endAngle:0 clockwise:YES];
    
    //4.画右边的半圆
    //计算右边半圆的圆心
    CGPoint topRightCurveCenter = CGPointMake(endPintLeftCurve.x + 3*curveRadius, endPintLeftCurve.y);
    [heartPath addArcWithCenter:topRightCurveCenter radius:curveRadius startAngle:PI endAngle:0 clockwise:YES];
    
    //5.画右边的弧形 贝塞尔曲线
    CGPoint rightControlPoint = CGPointMake(endPintLeftCurve.x + 4*curveRadius, endPintLeftCurve.y + curveRadius);
    [heartPath addQuadCurveToPoint:bottomLocation controlPoint:rightControlPoint];
    
    
    [heartPath fill];
    heartPath.lineWidth = 1;
    heartPath.lineCapStyle = kCGLineCapRound;   //线条拐点
    heartPath.lineJoinStyle = kCGLineCapRound;  //终点处理
    [heartPath stroke];
}
  • 执行动画:
    通过提供一个公开的- (void)animateInView:(UIView *)view;方法供外部调用。里面分别加了四个动画效果:1开始的跳动显现2过程中旋转3按照贝塞尔曲线移动一段距离4结束动画,此方法的实现如下:
- (void)animateInView:(UIView *)view
{
    NSTimeInterval totalAnimationDuration = 6;
    CGFloat heartWidth = CGRectGetWidth(self.bounds);
    CGFloat heartCenterX = self.center.x;
    CGFloat viewHeight = CGRectGetHeight(view.bounds);
    
    //初始化
    self.transform = CGAffineTransformMakeScale(0, 0);
    self.alpha = 0;
    
    //1.跳动显现出来
    [UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.transform = CGAffineTransformIdentity;
        self.alpha = 0.9;
    } completion:NULL];
    
    //2.旋转角度
    NSInteger i = arc4random_uniform(2);        //0 1 两个值 不含上界
    NSInteger rotationDirection = 1 - (2*i);    // -1 OR 1
    NSInteger rotationFraction = arc4random_uniform(10);
    [UIView animateWithDuration:totalAnimationDuration animations:^{
        self.transform = CGAffineTransformMakeRotation(rotationDirection * PI/(6 + rotationFraction * 0.2));
    } completion:NULL];
    
    //3.按照贝赛尔曲线移动帧动画
    UIBezierPath *heartTravelPath = [UIBezierPath bezierPath];
    [heartTravelPath moveToPoint:self.center];
    //生成结束点 在一定范围内随机 和旋转方向同一侧
    CGPoint endPoint = CGPointMake(heartCenterX + rotationDirection * 2 * heartWidth, viewHeight / 6.0 + arc4random_uniform(viewHeight/4.0));   //以至少高度的六分之一为起点加上 0到四分之一高度之间的随机数
    //生成控制点 也是在一定范围内随机
    NSInteger j = arc4random_uniform(2);
    NSInteger travelDirection = 1 - (2 * i);
    CGFloat xDelta = (heartWidth/2.0 + arc4random_uniform(2*heartWidth)) * travelDirection * 2; //这个2可以控制宽度的倍数
    CGFloat yDelta = MAX(endPoint.y, MAX(arc4random_uniform(8*heartWidth), heartWidth));
    CGPoint controlP1 = CGPointMake(heartCenterX + xDelta, viewHeight - yDelta);
    CGPoint controlP2 = CGPointMake(heartCenterX - 2*xDelta, yDelta);
    [heartTravelPath addCurveToPoint:endPoint controlPoint1:controlP1 controlPoint2:controlP2];
    
    CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    keyFrameAnimation.path = heartTravelPath.CGPath;
    keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    keyFrameAnimation.duration = totalAnimationDuration + endPoint.y / viewHeight;
    
    [self.layer addAnimation:keyFrameAnimation forKey:@"positionOnPath"];
    
    //4.移除动画收尾 Alpha & remove from superview
    [UIView animateWithDuration:totalAnimationDuration animations:^{
        self.alpha = 0.0;
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}

很小的一个demo,积小流成江海。完整demo的github地址:心形飘动demo请点击此链接进行下载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,857评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 2016-01-30 13:30:48 一个让你留在北京的理由 问过很多刚毕业的年轻人,以后想在哪座城市发展,很多...
    霓为衣兮风为马阅读 554评论 0 1
  • 经过一段时间的胡思乱想、胡作非为之后,我决心胡说八道一番,因为本次大会实在是“后患无穷”,这一切都得益于洋葱数学团...
    小幸甫阅读 3,047评论 2 10
  • 我的一輩子就是一張紙 某年某月某日 是我的生產日期 那孩提的哭啼 童年的歡聲笑語 少年時桀驁不馴的叛逆 愛情里患得...
    你咸我淡阅读 210评论 0 1