然则高校时候的技术水平威尼斯人娱乐,大家介绍了贝塞尔曲线的绘图

高校时候,有1段时间对flash比较感兴趣。去体育场地借了壹本很厚很厚的falsh书籍。

在贝塞尔曲线(一)中,我们介绍了贝塞尔曲线的绘图,可是那是永恒的,运用景况很少,运用更加多的是一对卡通效果。
而前者首要的成效就是承受貌美如花,所以精晓一定的动画技术如故有不能缺少的。
从而啊,作者就开始从简单的日益斟酌吗。

 

下推动画片

第贰是之类的法力:

威尼斯人娱乐 1

下带动画.gif

率先要求分析多少个难题:

  1. 什么绘制二阶曲线
  2. 何以让曲线跟随着下拉展开转变

难题的缓解有很种种,我写下的只是自家的解决思路:

1. 创建一个视图,重写它的drawRect:方法

UIBezierPath *bezier = [UIBezierPath bezierPath];
UIColor *color = hexStrColor(@"#FF8C69");
[color set];
bezier.lineWidth = 1.0;
[bezier moveToPoint:(CGPoint){0,0}];
[bezier addQuadCurveToPoint:(CGPoint){self.width,0} controlPoint:(CGPoint){self.width/2,self.offsetY}];
[bezier fill];

通过下边包车型大巴办法,我们绘制了二阶曲线,那么便是不留余地第2个难题了。

想让我们的报表下拉的时候,视图也跟着变化,那么必然需求通晓我们表格下拉的切切实实数值,所以须要完成UIScrollViewDelegate的scrollViewDidScroll方法

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{}

通过该方法大家实时的理利尿格的Y轴偏移量,所以大家还索要在事先的视图中添加3个变量:
@property (nonatomic,readwrite,unsafe_unretained)CGFloat offsetY;
经过该变量来实时的控制二阶曲线的controlPoint参数的Y值。

接下去,大家在scrollViewDidScroll方法中写下如下代码。

self.headerView.offsetY = -scrollView.contentOffset.y;
[self.headerView setNeedsDisplay];
[self.headerView setFrame:(CGRect){0,statusBarHeight,kSCREENWIDTH,- scrollView.contentOffset.y}];

因为我们须要在滑行的时候实时的改观曲线的拐点,然后生成对应的曲线。也等于大家需求实时的重复绘制视图,也便是调用drawRect:
方法.所以大家要求调用setNeedsDisplay方法。通过在表面调用setNeedsDisplay能够是视图重新调用drawRect方法

setNeedsLayout会默许调用layoutSubViews,
setNeedsDisplay会调用drawRect:方法

翻了几页之后,就再未有将来看过。影像对比深的是我说他用flash实现了三个龙卷风效果。

加载动画

接下去大家再做个加载动画,具体的效果如下:

威尼斯人娱乐 2

加载动画.gif

那是个基于路径变化的动画,也是自身在很多软件上时时看看的壹种加载动画。所以就协调摸索能或无法做不出去。
先成立四个球,哈哈,先把我们要玩的球画出来:

CGFloat radius = 20;
CGFloat marginLeft = 10;
//第一颗球
CAShapeLayer *fLayer = [CAShapeLayer new];
fLayer.backgroundColor =  getColor(102, 170, 238, 1).CGColor;
[fLayer setFrame:(CGRect){self.width/2-(radius*2+marginLeft*2)/2,self.height/2,radius,radius}];
fLayer.cornerRadius = radius/2;
//第二颗球
CAShapeLayer *sLayer = [CAShapeLayer new];
sLayer.backgroundColor = getColor(102, 170, 238, 0.5).CGColor;
[sLayer setFrame:(CGRect){marginLeft(fLayer)+marginLeft,self.height/2,radius,radius}];
sLayer.cornerRadius = radius/2;
//第三颗球
CAShapeLayer *tLayer = [CAShapeLayer new];
tLayer.backgroundColor = getColor(102, 170, 238, 0.2).CGColor;
[tLayer setFrame:(CGRect){marginLeft(sLayer)+marginLeft,self.height/2,radius,radius}];
tLayer.cornerRadius = radius/2;


self.layer_list = [NSArray arrayWithObjects:fLayer,sLayer,tLayer,nil];
[self.layer addSublayer:fLayer];
[self.layer addSublayer:sLayer];
[self.layer addSublayer:tLayer];

球画好了大家即将开端切磋它的活动轨迹了。通过一些考查我们分析得出了上面包车型地铁位移轨迹:

威尼斯人娱乐 3

率先课球的运动动画.gif

威尼斯人娱乐 4

第3颗球运动动画.gif

威尼斯人娱乐 5

其3颗球运动动画.gif

通过观察,第2颗球的位移轨迹其实正是2个上半圆加上3个下半圆的路线动画。那么只需求画三个半圆就解决的事咯?大家来试一下

绘图圆的参考图:

威尼斯人娱乐 6

弧线参考图.png

首先个半圆是以四个圆的中央点为圆心绘制的弧形,
第一个半圆是 π -> 0° 顺时针运动,然后π -> 0°逆时针运动

威尼斯人娱乐 7

先是颗球的移位轨迹.png

CAShapeLayer *fLayer = self.layer_list[0];
CAShapeLayer *testLayer = [CAShapeLayer new];
testLayer.fillColor = [UIColor clearColor].CGColor;
testLayer.borderWidth = 1.0f;
testLayer.strokeColor = hexStrColor(@"#AA8C69").CGColor;

UIBezierPath *semicirclePath = [UIBezierPath bezierPath];
//上半圆
[semicirclePath addArcWithCenter:(CGPoint){fLayer.frame.origin.x+25,fLayer.frame.origin.y+10}
                           radius:15
                       startAngle:M_PI
                         endAngle:0
                        clockwise:YES];
//下半圆
[semicirclePath addArcWithCenter:(CGPoint){sLayer.frame.origin.x+25,sLayer.frame.origin.y+10}
                           radius:15
                       startAngle:M_PI
                         endAngle:0
                        clockwise:NO];
testLayer.path = semicirclePathA.CGPath;
[self.layer addSublayer:testLayer];

率先颗球的轨迹我们领略将来我们来安装第一颗球的轨迹:
0° -> π 顺时针运动

威尼斯人娱乐 8

其次颗球的移动轨迹.png

    CAShapeLayer *fLayer = self.layer_list[0];
    CAShapeLayer *sLayer = self.layer_list[1];
    //第二段动画
    CAShapeLayer *testLeftLayer = [CAShapeLayer new];
    testLeftLayer.fillColor = [UIColor clearColor].CGColor;
    testLeftLayer.borderWidth = 1.f;
    testLeftLayer.strokeColor = [UIColor redColor].CGColor;
    UIBezierPath *leftPath = [UIBezierPath bezierPath];
    [leftPath addArcWithCenter:(CGPoint){fLayer.frame.origin.x+25,fLayer.frame.origin.y+10} 
                        radius:15 startAngle:0 endAngle:M_PI clockwise:YES];
    testLeftLayer.path = leftPath.CGPath;
    [self.layer addSublayer:testLeftLayer];

咱俩再来看看第3颗球:
0° -> π 逆时针运动

威尼斯人娱乐 9

其3颗球的移位轨迹.png

    CAShapeLayer *sLayer = self.layer_list[1];
    CAShapeLayer *tLayer = self.layer_list[2];
    //第三段动画
    CAShapeLayer *testRightLayer = [CAShapeLayer new];
    testRightLayer.fillColor = [UIColor clearColor].CGColor;
    testRightLayer.borderWidth = duration;
    testRightLayer.strokeColor = [UIColor blueColor].CGColor;

    UIBezierPath *rightPath = [UIBezierPath bezierPath];
    [rightPath addArcWithCenter:(CGPoint){sLayer.frame.origin.x+25,tLayer.frame.origin.y+10} 
                         radius:15 startAngle:0 endAngle:M_PI clockwise:NO];
    testRightLayer.path = rightPath.CGPath;
    [self.layer addSublayer:testRightLayer];

终极的静态效果图如下:

威尼斯人娱乐 10

静态效果图.png

设定好轨迹之后我们就来安装它们的动画片效果,动画效果就要采纳大家上1篇中涉嫌的机要帧动画了.
鉴于三个卡通具有同样的性子设置,所以大家最为是包装一下,提取出它们会有变化的数值。
诸如,动画的信赖视图会变,它们的位移path会变,所以提取出那个参数。

- (void)keyFrameAnimationWithLayer:(CALayer *)layer path:(UIBezierPath *)path;

    CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    keyAnimation.path = path.CGPath;
    keyAnimation.fillMode = kCAFillModeForwards;
    keyAnimation.calculationMode = kCAAnimationPaced;
    keyAnimation.removedOnCompletion = NO;
    keyAnimation.duration = duration;
    keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    keyAnimation.rotationMode = kCAAnimationRotateAuto;
    keyAnimation.repeatCount = MAXFLOAT;
    keyAnimation.calculationMode = kCAAnimationCubic;
    [layer addAnimation:keyAnimation forKey:@"keyFrameAnimation"];

现实的参数消息已经在上一篇中提过了,这里就不说了。
接下来大家起始调用:

//调用第一颗球
[self keyFrameAnimationWithLayer:fLayer path:semicirclePath];

威尼斯人娱乐 11

首先颗球卡顿的动画.gif

大家运营之后会意识在多个圆的交界处,卡顿了刹那间下(关于这一个题材,笔者尝试调整了动画的timingFunction属性还有calculationMode都不可能很好的缓解这一个难点,小编算计是出于三个路子是分离绘制的原因,具体的原因还在琢磨个中。)
只是本人要么找到了消除办法:
安装四个路子,然后将路径进行联合成一个途径:

    UIBezierPath *semicirclePathA = [UIBezierPath bezierPath];
    [semicirclePathA addArcWithCenter:(CGPoint){fLayer.frame.origin.x+25,fLayer.frame.origin.y+10} radius:15 startAngle:M_PI endAngle:0 clockwise:YES];
    UIBezierPath *semicirclePathB = [UIBezierPath bezierPath];
    [semicirclePathB addArcWithCenter:(CGPoint){sLayer.frame.origin.x+25,sLayer.frame.origin.y+10} radius:15 startAngle:M_PI endAngle:0 clockwise:NO];
    [semicirclePathA appendPath:semicirclePathB];
    testLayer.path = semicirclePathA.CGPath;
    [self.layer addSublayer:testLayer];

运作之后,能够观察成效,如巧克力般丝滑的觉得:

威尼斯人娱乐 12

先是课球的移位动画.gif

画好第2个球之后,大家再来画其余的五个球,基本就1样了,只要调用

- (void)keyFrameAnimationWithLayer:(CALayer *)layer path:(UIBezierPath *)path;

方式就足以了。

效率如下:

威尼斯人娱乐 13

三颗球运动动画.gif

只是完成的效劳并不及意,它们的颜料变化并不是潜移默化的,看起来并不佳,所以咱们还亟需添加颜色变换的卡通片
观测原来的意义总括如下:

  1. 首先颗球从开端到转到末了的时候,颜色从深色变为了浅色。所以我们能够设定它的变化值为
    一 -> 0.二.
  2. 第叁颗球原本是浅色然后旋转到第二的职务时是深色。所以大家可以设定它的变化值为
    0.伍 -> 一.
  3. 其三颗球原本是最浅的下一场旋转到第壹的地方时,颜色变深了有个别。所以大家设定它的变化值
    0.二 -> 0.5.

动画因为只是三个值得变化 , FromValue -> toValue ,
我们接纳CABasicAnimation就能够轻松实现效果.
小编们1样来封装该卡通:

- (void)colorGradientAnimationWithLayer:(CALayer *)layer fromValue:(id)fromValue toValue:(id)toValue{
    CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    alphaAnimation.fromValue = fromValue;
    alphaAnimation.toValue = toValue;
    alphaAnimation.duration = duration;
    alphaAnimation.repeatCount = MAXFLOAT;
    [layer addAnimation:alphaAnimation forKey:@"anmiationAlpha"];
}

调用:

//第一颗球的变化
[self colorGradientAnimationWithLayer:fLayer
                                    fromValue:(__bridge id _Nullable)(getColor(102, 170, 238, 1)).CGColor
                                      toValue:(__bridge id _Nullable)(getColor(102, 170, 238, 0.2)).CGColor];
//第二颗球的变化
[self colorGradientAnimationWithLayer:sLayer
                                    fromValue:(__bridge id _Nullable)(getColor(102, 170, 238, 0.5)).CGColor
                                      toValue:(__bridge id _Nullable)(getColor(102, 170, 238, 0.1)).CGColor];
//第三颗球的变化
[self colorGradientAnimationWithLayer:tLayer
                                fromValue:(__bridge id _Nullable)(getColor(102, 170, 238, 0.2)).CGColor
                                  toValue:(__bridge id _Nullable)(getColor(102, 170, 238, 0.5)).CGColor];

直接到将来自笔者也尚未观看那些效果。

在制程中出现的气象:

一.动画闪烁
keyAnimation.fillMode = kCAFillModeForwards;
能够添加该属性,该属性表示保留动画甘休时的功效。
但丰盛之后发现照旧这些,最终发现实际动画停止的坐标点不平常。

__bridge 主假使因为我们在编写程序的时候还会用到 CoreFoundation(CF)
框架的指标,CF和 OC 对象期间的类型转换就必要采用__bridge

最终正是大家需求的效能了。

威尼斯人娱乐 14

加载动画.gif

DEMO:
https://github.com/yanggenwei/GWAnimation/tree/master

笔者也早已想过完成一下。不过大学时候的技术水平,也支撑不起这几个想法。稳步就记不清了。

突发性间自身见状了离心运动。突然就悟出1个写法。

演示地址如下:

http://suohb.com/work/wind2.htm

点击查阅效果

最后效果图如下:

威尼斯人娱乐 15

 

沙尘卷风,大家可以作为三个向上旋转的气流。

风自个儿是不可知的,大家就用有个别质点的移动轨迹画出来,表示风。

从上向下俯视,就是这么,七个质点做离心运动的门径。

威尼斯人娱乐 16

从侧面看,是这么在,一个质点绕Y轴左右摇摆,摆动越来越大的的位移的不二等秘书籍。

威尼斯人娱乐 17

大家就用那么些来做为侧视图的成效,来做一个二D的风暴。

 

那就是说开始代码设计:

大家定义叁个点,这么些点Y轴上恒定速率运动,X轴上,向那中线方向有一个向心力G。一旦点运动当先那条中线,向心力倒转为-G。

那样就会画出地点侧视图的法力。

 

威尼斯人娱乐 18

 

下一场各种周期都新增部分这样的点,画出轨道。如图;

威尼斯人娱乐 19

大抵那样就早已成功了,大家不须要画出总体的不贰秘诀,只要画出最新的一段就可以。

当到达一定中度之后,就将那条线稳步移除出去。就取得终极效果

威尼斯人娱乐 20

 

代码如下:

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta http-equiv="Pragma" content="no-cache" />
 5 <meta http-equiv="Cache-Control" content="no-cache" />
 6 <meta http-equiv="Expires" content="0" />
 7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 8 <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
 9 <style type="text/css">
10 html{
11     height: 100%;
12 }
13 html,body,ul,li,canvas{
14     margin: 0;
15     padding: 0;
16 }
17 </style>
18 </head>
19 <body bgcolor="#000000">
20 <canvas id="knife"></canvas>
21 </body>
22 <script>
23 var canvas = document.getElementById("knife");
24 canvas.style.position = "absolute" ;
25 canvas.style.top = 0 ;
26 var w = window.innerWidth ;
27 var h = window.innerHeight ;
28 canvas.width = w ;
29 canvas.height = h ;
30 var cxt = canvas.getContext("2d");
31 cxt.strokeStyle = "#FFF" ;
32 var list = [];
33 var G = 0.4 ;//向心加速度
34 var SPEED_Y = -1 ;//向上速度
35 var centerLine = w/2 ;//龙卷风中线
36 function addLine(){
37     var LEN = 2 ;
38     for(var i = 0 ;i < LEN ; i ++){
39         list.push({
40             x:w/2,
41             y:h/1.3,
42             g:G,
43             c:centerLine+2*Math.random(),
44             sx:(Math.random()-0.5)*4,
45             sy:SPEED_Y+0.5*(Math.random()-0.5),
46             len:Math.round(Math.random()*10+5),
47             list:[{x:w/2,y:h/1.3}]
48         });
49     }
50 }
51 function step(){
52     cxt.clearRect(0,0,w,h);
53     addLine();
54     var obj ;
55     for(var i = 0 ; i < list.length; i ++){
56         obj = list[i] ;
57         if(obj.y < h/2.5){//如果超过这个高度,就删除一个点
58             obj.len -- ;
59             if(obj.len == 0){
60                 list.splice(i,1);
61                 i -- ;
62                 continue ;
63             }
64         }
65         obj.x += obj.sx ;
66         obj.y += obj.sy ;
67         obj.sx += obj.g ;
68         obj.g = obj.x > obj.c ? -G : G ;
69         obj.list.unshift({x:obj.x,y:obj.y});//记录下质点运动轨迹
70         obj.list = obj.list.slice(0,obj.len);//仅仅画出其中一段线就好
71         //画出所有点的连线
72         cxt.beginPath();
73         cxt.moveTo(obj.list[0].x,obj.list[0].y);
74         for(var j = 1 ; j < obj.list.length; j ++){
75             cxt.lineTo(obj.list[j].x,obj.list[j].y);
76 
77         }
78         cxt.stroke();
79     }
80     requestAnimationFrame(step);
81 }
82 requestAnimationFrame(step);
83 </script>
84 </html>

 

更加多特效请关切群众号:

威尼斯人娱乐 21

 

相关文章