【澳门威尼斯人登陆】css3动画之圆形运动轨迹,css3动画轨迹

by admin on 2019年9月8日

H5 动画:轨迹移动

2017/11/10 · HTML5 ·
动画

原文出处:
凹凸实验室   

 

动画,是指由许多帧静止的画面,以一定的速度(如每秒16张)连续播放时,肉眼因视觉残象产生错觉,而误以为画面活动的作品。

在 Web
开发中,经常需要实现各种动画效果,例如:移动、变形、透明度变化等,今天我们主要来讨论各种移动的实现。

KeyFrameAnimation来源于动画产业,最早做动画片的时候,会分为几个角色,牛点的人会根据剧情等因素把场景中的关键画面画出来,剩下的不那么牛的人则根据这些关键画面把一些过渡性的图片补足,假设一秒需要20张图片,关键图片可能有5张,剩下的15张则根据这5张的内容来补齐,这就是最早的key
frame的来源。其实在视频编解码中也经常会碰到类似的属于,比如KeyFrame和I帧P帧这些名词,都是跟这些有关的。

css3动画之圆形运动轨迹,css3动画轨迹

css3中通过@keyframes定义动画,animation设置动画属性,从而实现动画效果;

在animation属性当中,可以规定动画的名称、整个动画的运行时间、运动的速度曲线以及其延迟时间、播放次数等。

动画。定时器


研究了个点赞动画,利用的技术有CAShapeLayer,UIBezierPath及核心动画。下面讲解怎么实现它。

直线移动

澳门威尼斯人登陆 1

通常可以直接由各个点的位置,以及到点的时间与整个动画持续时间的比值,写出类似下面的代码并可实现动画。

JavaScript

.cray { animation: move 2s alternate infinite; } @keyframes move { 0% {
transform: translate(0, 0); } 30% { transform: translate(100px, 0); }
60% { transform: translate(100px, 100px); } 100% { transform:
translate(200px, 0); } }

1
2
3
4
5
6
7
8
9
.cray {
  animation: move 2s alternate infinite;
}
@keyframes move {
  0% { transform: translate(0, 0); }
  30% { transform: translate(100px, 0); }
  60% { transform: translate(100px, 100px); }
  100% { transform: translate(200px, 0); }
}

在iOS中,如果你使用CAKeyFrameAnimation,则需要提供一些关键点,然后iOS在显示的过程中会根据这些信息自动补齐过渡性的内容。

animation

animation作为一个复合属性,包括了以下动画属性。

  • ### animation-name ————————————-规定动画名称

  • ### animation-duration ———————————规定动画完成一次的时间

  • ### animation-timing-function  ———————-规定动画的运动速度曲线

  • ### animation-delay  ————————————规定动画的延迟时间

  • ### animation-iteration-count  ———————–规定动画的播放次数

  • ### animation-direction   ——————————规定动画下一周期是否逆向开始

  • ### animation-fill-mode  ——————————-规定动画时间之外的状态

  • ### animation-play-state  ——————————规定动画的运行和暂停

1.视图移动

{

//在这里定义全局变量也可以,属性不能声明在主文件

UIView *_view1;

//标记view1是否正在移动

BOOL isMoving;

}

//属性如果不在.h文件中声明, @property
在这里声明的属性,本类可以调用,在其他类中,不能调用

//@property (nonatomic,assign)int age;

//方法不在.h文件中声明,在这里声明的方法,本类可以调用,在其他类中,不能调用

//-(void)eat;

– (void)viewDidLoad {

[super viewDidLoad];

//写方块

_view1= [[UIView alloc] initWithFrame:CGRectMake(20, 20, 40, 40)];

_view1.backgroundColor= [UIColor orangeColor];

[self.view addSubview:_view1];

//用tag标记视图view1的运动状态,0表示停止或者将要停止状态,1表示运动状态

_view1.tag= 0;

//用isMoving标记view1的运动状态,NO表示已经停止,YES表示还没停止(动画还在执行)

isMoving=NO;

}

//XIB。点击开始按钮调用的方法

–  (IBAction)start:(id)sender{

//bug1:如果连续点击两次开始按钮,会同时执行两个动画,而且两个动画执行的对象都是view1,所以发生干涉,造成混乱的现象

//解决方法:在点开始按钮时,判断一下view1的运动状态,tag值为0并不能保证动画已经结束,而isMoving
= NO,可以确认动画已经停止

//bug2:连续点击开始和暂停按钮会出现干涉

//解决方法:isMoving

if(isMoving==NO) {

//改变view1的运动状态

_view1.tag= 1;

isMoving=YES;

[self move1];

}

}

– (void)move1 {

//如果tag值为1,表示正在运动,则执行动画

if(_view1.tag== 1) {

[UIViewbegin Animations:nil context:nil];

[UIView setAnimationDuration:1];

[UIView setAnimationDelegate:self];

[UIView setAnimationDidStopSelector:@selector(move2)];

_view1.center=CGPointMake(280, 40);

//    4,提交

[UIView commitAnimations];

}

//tag值为0,表示现在是停止状态,跳出循环,不在执行动画,动画结束

else{

isMoving=NO;

}

}

– (void)move2 {

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:1];

_view1.center=CGPointMake(280, 440);

[UIView setAnimationDelegate:self];

[UIView setAnimationDidStopSelector:@selector(move3)];

[UIView commitAnimations];

}

– (void)move3 {

[UIView beginAnimations:nilcontext:nil];

[UIView setAnimationDuration:1];

_view1.center=CGPointMake(40, 440);

[UIView setAnimationDelegate:self];

[UIView setAnimationDidStopSelector:@selector(move4)];

[UIView commitAnimations];

}

– (void)move4 {

[UIView beginAnimations:nil context:nil];

[UIViewset AnimationDuration:1];

_view1.center=CGPointMake(40, 40);

[UIView setAnimationDelegate:self];

[UIView setAnimationDidStopSelector:@selector(move1)];

[UIView commitAnimations];

}

//点击停止按钮调用的方法

– (IBAction)stop:(id)sender {

//把tag值改为0,表示不需要再移动了

_view1.tag= 0;

}

@end


绘制出❤️的形状,所以用到CAShapeLayer和UIBezierPath配合。首先自定义一个LikeAnimationLayer继承自CAShapeLayer。然后利用贝瑟尔曲线绘制出❤️。

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface LikeAnimationLayer : CAShapeLayer

- (instancetype)initWithSuperView:(UIView *)superView;

/**
给layer添加动画
*/
- (void)addAnimation;

@end

- (instancetype)initWithSuperView:(UIView *)superView
{
    self = [super init];
    if (self) {

        self.backgroundColor = [UIColor clearColor].CGColor;
        self.bounds = CGRectMake(0, 0, 40, 40);
        self.anchorPoint = CGPointMake(0.5, 1);
        //画路径,❤️
        self.path = [self likePath];
        self.strokeColor = [UIColor whiteColor].CGColor;
        self.lineWidth = 1.0;
        self.fillColor = [UIColor colorWithRed:(arc4random_uniform(256))/255.0 green:(arc4random_uniform(256))/255.0 blue:(arc4random_uniform(256))/255.0 alpha:1].CGColor;
       self.superView = superView;



    }
    return self;
}

- (CGPathRef)likePath
{
    //心距离边缘的距离
    CGFloat drawingPadding = 2.0;
    //向下取整floor
    CGFloat curveRadius = floor((kWidth - 2*drawingPadding) / 4.0);
    UIBezierPath *path = [UIBezierPath bezierPath];
    //最下面的点(20,38)
     CGPoint tipLocation = CGPointMake(floor(kWidth / 2.0), kHeight - drawingPadding);
    [path moveToPoint:tipLocation];
    //左上的点(2,13)
    CGPoint topLeftCurveStart = CGPointMake(drawingPadding, floor(kHeight / 3));
    //画二元曲线左边的心的曲线
    [path addQuadCurveToPoint:topLeftCurveStart controlPoint:CGPointMake(topLeftCurveStart.x, topLeftCurveStart.y + curveRadius)];
    //画左边上面的半圆
    [path addArcWithCenter:CGPointMake(topLeftCurveStart.x + curveRadius, topLeftCurveStart.y) radius:curveRadius startAngle:M_PI endAngle:0 clockwise:YES];
    //右边的半圆
    CGPoint topRightCurveStart = CGPointMake(topLeftCurveStart.x + 2*curveRadius, topLeftCurveStart.y);
    [path addArcWithCenter:CGPointMake(topRightCurveStart.x + curveRadius, topRightCurveStart.y) radius:curveRadius startAngle:M_PI endAngle:0 clockwise:YES];
    //画二元曲线右边的心的曲线
    CGPoint topRightCurveEnd = CGPointMake(topLeftCurveStart.x + 4*curveRadius, topRightCurveStart.y);
    [path addQuadCurveToPoint:tipLocation controlPoint:CGPointMake(topRightCurveEnd.x, topRightCurveEnd.y + curveRadius)];
    path.lineCapStyle = kCGLineCapRound;
    path.lineJoinStyle = kCGLineCapRound;

    return path.CGPath;
}

曲线移动

澳门威尼斯人登陆 2

在 CSS 中可以通过 transform-origin 配合 rotate
实现曲线移动,不过这种 曲线 都是圆的一部分且不太好控制。

这种移动我们可以把它拆分成两个方向的运动叠加,如

澳门威尼斯人登陆 3

更详细的说明可以参考这篇文章
《curved-path-animations-in-css》。

我们可以用下面一个飞机飞行线路的例子来说明

animation-timing-function

规定动画的速度曲线。默认是 “ease”。常用的运动速度曲线还有以下几种:

  • linear:线性过渡。
  • ease-in:由慢到快。
  • ease-out:由快到慢。
  • ease-in-out:由慢到快再到慢。

也可以直接使用贝塞尔曲线规定运行的速度曲线,贝塞尔曲线的4个数值需在[0,
1]区间内。

//小球弹跳

{

UIView *_view1;

}

– (void)viewDidLoad {

[super viewDidLoad];

_view1 =  [[UIView alloc] initWithFrame:CGRectMake(160, 0, 30,
30)];

_view1.backgroundColor= [UIColorgreenColor];

_view1.layer.cornerRadius= 15;

_view1.alpha= 0.5;

[self.view addSubview:_view1];

[NSTimer scheduledTimerWithTimeInterval:0.01
target:selfselector:@selector(viewMove) userInfo:nil repeats:YES];

}

//视图移动的方法

– (void)viewMove {

//_view1.center = CGPointMake(100, 100);

//让view1向下移动

为这个❤️添加上动画。动画分为两个动画组。第一个动画组是将layer的scale从0到1,并且改变它的透明度从0到1。利用了iOS7出来的弹簧动画CASpringAnimation。接着就是layer沿着一个随机的轨迹从一个点移动到另一个点,我是从屏幕下方移动到屏幕上方。利用三次贝塞尔曲线,实现layer的运动轨迹。

- (void)addAnimation
{

    CASpringAnimation *springAnimal = [CASpringAnimation animationWithKeyPath:@"transform.scale"];
    springAnimal.fromValue = @(0);
    springAnimal.toValue = @(1.0);
    //质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大默认是1 必须大于0
//    若你设置的值小于0  会有CoreAnimation: mass must be greater than 0.这个信息提示你
//    并且把你的小于0的值改成1
//    对象质量 质量越大 弹性越大 需要的动画时间越长
    springAnimal.mass = 1.0;
//    必须大于0  默认是100
//    若设置的小于0 会给你一个提示 并把值改成100
//    刚度系数,刚度系数越大,产生形变的力就越大,运动越快。
    springAnimal.stiffness = 90;
//    默认是10 必须大于或者等于0
//    若设置的小于0 会给你一个提示 并把值改成10
//    阻尼系数 阻止弹簧伸缩的系数 阻尼系数越大,停止越快。时间越短
     springAnimal.damping = 10;
//    默认是0
//    初始速度,正负代表方向,数值代表大小
     springAnimal.initialVelocity = 2;
//    计算从开始到结束的动画的时间,根据当前的参数估算时间
//    只读的,不能赋值
     springAnimal.duration = springAnimal.settlingDuration;


    CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    alphaAnimation.fromValue = @0;
    alphaAnimation.toValue = @1;

    CAAnimationGroup *Scalegroup = [CAAnimationGroup animation];
    Scalegroup.animations = @[springAnimal,alphaAnimation];
    Scalegroup.duration = 0.5;
    Scalegroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    [self addAnimation:Scalegroup forKey:@"scaleAndalphaAnimation"];


    // 随机数(0,1)
    NSInteger i = arc4random_uniform(2);
    //移动的方向(-1 ,1)
    NSInteger moveDirection = 1 - (2*i);

    // 绘制路径
    UIBezierPath *heartTravelPath = [UIBezierPath bezierPath];
    //先移动到心的中心点这是起点
    [heartTravelPath moveToPoint:self.position];

    CGPoint endPoint = CGPointMake(self.position.x + (moveDirection) * arc4random_uniform(kWidth), self.superView.frame.size.height/6.0 + arc4random_uniform(self.superView.frame.size.height/4.0));

    CGFloat x = (kWidth/2.0 + arc4random_uniform(kWidth)) * moveDirection;
    CGFloat y = MAX(endPoint.y ,MAX(arc4random_uniform(8*kWidth), kWidth));
    //两个控点
    CGPoint controlPoint1 = CGPointMake(self.position.x + x, self.superView.frame.size.height - y);
    CGPoint controlPoint2 = CGPointMake(self.position.x - 2*x, y);

    [heartTravelPath addCurveToPoint:endPoint controlPoint1:controlPoint1 controlPoint2:controlPoint2];

    CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    keyFrameAnimation.path = heartTravelPath.CGPath;
    keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.fromValue = @1;
    opacityAnimation.toValue = @0;

    CAAnimationGroup *positionGroup = [CAAnimationGroup animation];
    positionGroup.animations = @[keyFrameAnimation,opacityAnimation];
    positionGroup.duration = liveAnimationDuration + endPoint.y/self.superView.frame.size.height;
    positionGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    positionGroup.delegate = self;
    //如果不加这句[self animationForKey:@"ani1"]是nil
    positionGroup.removedOnCompletion = NO;
    positionGroup.fillMode = kCAFillModeForwards;
    //kvc记录layer的值方便在代理方法里移除
    [positionGroup setValue:self forKey:@"likeLayer"];
    [self addAnimation:positionGroup forKey:@"positionGroup"];

}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{

    if ([self animationForKey:@"positionGroup"] == anim) {

        CALayer *layer = [anim valueForKey:@"likeLayer"];
        if (layer) {
            [layer removeFromSuperlayer];
        }
    }
}

澳门威尼斯人登陆 4

SUNLiveAnimation.gif

路径移动

澳门威尼斯人登陆 5

这也是曲线移动,但是想像上面那样,这个很难拆分成几个方向的运动叠加。这样的移动路径可以尝试以下几个方法:

  • SVG Animation

这样的路径可以比较好的用 SVG path 来描述,然后使用 SVG Animation
做跟随动画,并可以达到预期的轨迹效果。

主要代码(在线示例):

JavaScript

<svg width=”420px” height=”260px” viewBox=”0 0 420 260″ version=”1.1″
xmlns=””
xmlns:xlink=”; <g stroke=”#979797″
stroke-width=”1″ fill=”none”> <path id=”motionPath”
d=”M370.378234,219.713623 C355.497359,218.517659 …” ></path>
</g> <g id=”cray” transform=”translate(0, -24)”
stroke=”#979797″> <image id=”cray-img”
xlink:href=”” x=”0″
y=”0″ width=”100px”/> </g> <animateMotion
xlink:href=”#cray” dur=”5s” begin=”0s” fill=”freeze”
repeatCount=”indefinite” rotate=”auto-reverse” > <mpath
xlink:href=”#motionPath” /> </animateMotion> </svg>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<svg width="420px" height="260px" viewBox="0 0 420 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g stroke="#979797" stroke-width="1" fill="none">
    <path id="motionPath" d="M370.378234,219.713623 C355.497359,218.517659 …" ></path>
  </g>
  <g id="cray" transform="translate(0, -24)" stroke="#979797">
   <image id="cray-img" xlink:href="http://7xt5iu.com1.z0.glb.clouddn.com/img/cray.png" x="0" y="0" width="100px"/>
  </g>
  <animateMotion
    xlink:href="#cray"
    dur="5s"
    begin="0s"
    fill="freeze"
    repeatCount="indefinite"
    rotate="auto-reverse"
  >
    <mpath xlink:href="#motionPath" />
  </animateMotion>
</svg>

效果:

澳门威尼斯人登陆 6

  • JavaScript

使用 JavaScript
可以直接操作元素进行运动,理论上可以实现任何动画,只是实现一些复杂的动画成本比较高,好在有各种已经开发好了的工具库可以供我们使用。例如,使用
Greensock 的 TweenMax 和 MorphSVGPlugin(收费),通过 MorphSVGPlugin
提供的 pathDataToBezier 方法将 SVG path 转成曲线数组,然后给 TweenMax
使用:

JavaScript

var hill = document.getElementById(‘hill’) var path =
MorphSVGPlugin.pathDataToBezier(“#motionPath”); TweenMax.to(hill, 5, {
bezier:{ values:path, type:”cubic”, autoRotate: 180 },
ease:Linear.easeNone, repeat: -1 })

1
2
3
4
5
6
7
8
9
10
11
var hill = document.getElementById(‘hill’)
var path = MorphSVGPlugin.pathDataToBezier("#motionPath");
TweenMax.to(hill, 5, {
  bezier:{
    values:path,
    type:"cubic",
    autoRotate: 180
  },
  ease:Linear.easeNone,
  repeat: -1
})

在线示例

  • CSS

实现动画,其实就是在相应的时间点做相应的“变化”。再回头看直线移动的实现方式,其实如果能给出足够多点的位置和该点的时间与持续时间的比值,那其实曲线也可以直接用
CSS 来实现。

很多时候设计师使用 AE
来设计动画,当我们拿到设计稿后,可以给动画增加关键帧,然后借助一些工具把关键帧的信息导出来,这里介绍一个
keyframes-cli,可以导出这样结构的数据

澳门威尼斯人登陆 7

从属性名字可以判断出来 X_POSITIONY_POSITIONxy
的位置信息,而 key_values 里的 data 就是我们需要的点位置
该点的时间与持续时间的比值 可以根据 start_frame 得出,
写个脚本把这些数据处理下,可得到类似下面的 CSS 代码

澳门威尼斯人登陆 8

设置的关键帧越多,动画会越流畅,但 CSS 也会增多。

注意:不是 AE 关键帧里所有的信息都可以导出来,还跟 AE
里使用的过渡属性有关,这里有介绍。

最后,总结一下,移动动画就是用一种合适的方式把时间和位置的变化关系展示出来。除了上面方法,肯定还有很多其他的方法和帮助工具,欢迎留言交流讨论。

感谢您的阅读,本文由 凹凸实验室
版权所有。如若转载,请注明出处:凹凸实验室()

1 赞 1 收藏
评论

澳门威尼斯人登陆 9

- (void)drawSpaceCurve
{
    // Create a path
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(0, 150)];
    [bezierPath addCurveToPoint:CGPointMake(300, 150)
                  controlPoint1:CGPointMake(75, 0)
                  controlPoint2:CGPointMake(225, 300)];

    // Draw the path using CAShapeLayer
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.path = bezierPath.CGPath;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.strokeColor = [UIColor redColor].CGColor;
    pathLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:pathLayer];

    // Add the ship
    CALayer *shipLayer = [CALayer layer];
    shipLayer.frame = CGRectMake(0, 0, 64, 64);
    shipLayer.position = CGPointMake(0, 150);
    shipLayer.contents = (__bridge id)[UIImage imageNamed:@"Ship"].CGImage;
    [self.view.layer addSublayer:shipLayer];

    // Create the keyframe animation
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    animation.duration = 4.0f;
    animation.path = bezierPath.CGPath;
    [shipLayer addAnimation:animation forKey:nil];
}

animation-direction

规定动画是否在下一周期逆向播放。默认是 “normal”。

  • reverse:反方向运动
  • alternate:先正常方向再反方向运动,持续交替
  • alternate-reverse:先反方向再正常方向运动,持续交替

/* //写法1

//获取view1的横纵坐标

float y = _view1.frame.origin.y;

float x = _view1.frame.origin.x;

//让改变横纵坐标

//x = arc4random()%320;

//y = arc4random()%480;

y ++;

x ++;

//边界判断

//重用原理:当视图移动到屏幕底端时,我们把它拿到屏幕顶端,继续下落

if (x == 320) {

x = -50;

}

if (y == 480) {

//从边界外滑进来比较自然

y = -50;

}

//重新定义view1的位置

//_view1.frame.size.width可以换成固定数字,但不方便改变,逻辑也比较不严谨

_view1.frame = CGRectMake(x, y, _view1.frame.size.width,
_view1.frame.size.height);

*/

demo地址

https://github.com/yinbowang/LikeAnimal

澳门威尼斯人登陆 10

animation-fill-mode

规定对象动画时间之外的状态。常用值如下:

  • none:默认值
  • forwards:设置对象状态为动画结束时的状态
  • backwards:设置对象状态为动画开始时的状态

/*  //写法2

//获取view1的frame

//CGRect结构体不用*

//rect中间变量可识别

CGRect rect = _view1.frame;

//改变矩形的坐标

rect.origin.y ++;

rect.origin.x ++;

//边界判断

if (rect.origin.x >=320) {

rect.origin.x = -50;

}

if (rect.origin.y >= 480) {

rect.origin.y = -50;

}

//重新定义view1的位置

_view1.frame = rect;

*/

//定义横纵坐标的变化值

static int a = 3;

static int b = 4;

//获取小球中心的横纵坐标

intx =_view1.center.x;

inty =_view1.center.y;

//改变横纵坐标

x += a;

y += b;

//边界判断

if(x >= 305) {

a = -3;

}

if(x <= 15) {

a = 3;

}

if(y >=465) {

b = -4;

}

if(y <=15) {

b = 4;

}

//刷新位置

_view1.center=CGPointMake(x, y);

}

轨迹动画1.png

圆形运动轨迹

实现代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>沿圆形轨迹运动</title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        html,body{
            height: 100%;
        }
        #trajectory {
            width: 300px;
            height: 300px;
            border: 4px solid #949494;
            border-radius: 50%;
            position: relative;
            left: calc(50% - 153px);
            top:calc(50% - 153px);
        }
        @keyframes moveX{
            0% {left: -22px;}
            100% {left: 282px;}
        }
        @keyframes moveY{
            0% {top: -22px;}
            100% {top: 282px;}
        }
        #move {
            width: 40px;
            height: 40px;
            font-size: 12px;
            background-color: #32c33a;
            border-radius: 50%;
            position: absolute;
            left:-22px;
            top:-22px;
            animation: moveX 4s cubic-bezier(0.36,0,0.64,1) -2s infinite alternate, moveY 4s cubic-bezier(0.36,0,0.64,1) 0s infinite alternate;
        }
    </style>
</head>
<body>
    <div id="trajectory">
        <div id="move">Immortal brother</div>
    </div>
</body>
</html>

 

 以上代码的注意点如下:

  • 对body高度100%的设置原因在于html5环境下body的默认高度为0
  • calc在使用过程中,值与值之间的“-”和“+”两端的空格必不可少
  • 动画当中的left和top值为物体运动的起始位置和结束位置,要注意border值
  • 动画一次执行的运动轨迹仅为一半
  • 速度曲线:cubic-bezier(0.36,0,0.64,1);
  • 两个方向的延迟时间的设置 X:-2s;Y : 0s
  • 先正方向再反方向持续交替运行 :alternate

css3中通过@keyframes定义动画,animation设置动画属性,从而实现动画效果;
在animation属性当中,可以规…

在代码运行中,我们确实看到了飞机的运行轨迹和我们定义的bezierPath一致,但有个问题,就是飞机的机头方向没有在运行过程中做调整,这便使动画看起来怪怪的,不过好在Apple已经预见到这个需求,所以在CAKeyFrameAnimation中提供了一个名为rotationMode的属性,当我们把这个属性设置为kCAAnimationRotateAuto时,飞机在运行过程中机头始终超前,实现了我们的需求。

animation.rotationMode = kCAAnimationRotateAuto;

另外在实际的动画应用中,我们经常会使用到多个动画效果一同展示的情况,这种情况我们可以通过CAAnimationGroup来实现,它的用法和单独设置一个动画的效果没有太大的区别,但当你把多种效果组合到一起,在展示的时候,就可以轻松完成多个效果的同时展示。

我们还是用上面的轨迹来演示,不过把飞机换成了一个色块,动画是使色块不但按照我们规定好的路径运动,并且在运动中进行颜色的变换。

- (void)testAnimationGroup
{
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(0, 150)];
    [bezierPath addCurveToPoint:CGPointMake(300, 150)
                  controlPoint1:CGPointMake(75, 0)
                  controlPoint2:CGPointMake(225, 300)];

    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.path = bezierPath.CGPath;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.strokeColor = [UIColor redColor].CGColor;
    pathLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:pathLayer];

    CALayer *colorLayer = [CALayer layer];
    colorLayer.frame = CGRectMake(0, 0, 64, 64);
    colorLayer.position = CGPointMake(0, 150);
    colorLayer.backgroundColor = [UIColor greenColor].CGColor;
    [self.view.layer addSublayer:colorLayer];

    CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
    animation1.keyPath = @"position";
    animation1.path = bezierPath.CGPath;
    animation1.rotationMode = kCAAnimationRotateAuto;

    CABasicAnimation *animation2 = [CABasicAnimation animation];
    animation2.keyPath = @"backgroundColor";
    animation2.toValue = (__bridge id)[UIColor redColor].CGColor;

    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[animation1, animation2];
    group.duration = 4.0f;

    [colorLayer addAnimation:group forKey:nil];
}

澳门威尼斯人登陆 11

轨迹动画2.png

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图