精华内容
下载资源
问答
  • 初识cocos2dx动作动画
    2020-05-27 22:01:51

    关于动作

    动作类(Action)
    动作类(Action)是所有动作的基类,它创建的一个对象代表一个动作。动作作用于Node,因此每个动作都需要由Node对象执行。动作类(Action)作为基类,实际上是一个接口,动作类的大多数实现类都派生于有限时间动作类(FiniteTimeAction)。

    在实际开发中我们通常用到两类动作-即时动作和持续动作,它们均继承于有限时间动作类。

    即时动作类
    	auto placeAction = Place::create(Point(10, 10));
    	Place:该动作用于将节点放置到某个指定位置,其作用与修改节点的position属性相同。
    
    	auto flipxAction = FlipX::create(true);
    	auto flipyAction = FlipY::create(true);
    	FlipX和FlipY:这两个动作分别用于将精灵沿X轴和Y轴反向显示,其作用与设置精灵的FlipX和FlipY属性相同,将其包装成动作是为了便于与其他动作进行组合。
    
    	auto hideAction = Hide::create();
    	auto showAction = Show::create();
    	Show和Hide:这两个动作分别用于显示和隐藏节点,其作用与设置节点的visible属性作用一样。
    
    	auto actionMoveDone = CallFuncN::create([&](Ref* sender){
            log("Clear memory");
        });
        auto moveTo = MoveTo::create(0.4f, Point(0, 0));
        auto action = Sequence::create(moveTo, actionMoveDone, NULL);
    	CallFunc系列动作包括CallFunc、CallFuncN两个动作,用来在动作中进行方法调用。在游戏中为了节约内存资源,我们可以在动作完成后调用相应函数清理内存。
    
    持续动作类
        MoveTo::create(float duration, const Point& position);
        MoveBy::create(float duration, const Point& position);
    	MoveTo和MoveBy:用于使节点做直线运动,设置了动作时间和终点位置,在规定时间内会移动到终点。
    
        JumpTo::create(float duration, const Point& position, float height, int jumps);
        JumpBy::create(float duration, const Point& position, float height, int jumps);
    	JumpTo和JumpBy:使节点以一定的轨迹跳跃到指定位置。
    
        ccBezierConfig bezier;
        bezier.controlPoint_1 = Point(0, 0);
        bezier.controlPoint_2 = Point(100, 100);
        bezier.endPosition = Point(50, 100);
        auto bezierAction = BezierTo::create(0.5f, bezier);
        BezierTo和BezierBy:使节点进行曲线运动,运动的轨迹由贝塞尔曲线描述。每条贝塞尔曲线都包含一个起点和一个终点。在一条曲线中,起点和终点各自包含一个控制点,而控制点到端点的连线称作控制线。控制点决定了曲线的形状,包含角度和长度两个参数
        使用时,我们要先创建ccBezierConfig结构体,设置好终点endPosition以及两个控制点controlPoint_1和controlPoint_2后,再把结构体传入BezierTo或BezierBy的初始化方法中。
    
        ScaleTo::create(float duration, float s);
        ScaleBy::create(float duration, float s);
    	ScaleTo和ScaleBy:产生缩放效果,使节点的缩放系数随时间线性变化。
    
        RotateTo::create(float duration, float deltaAngle);
        RotateBy::create(float duration, float deltaAngle);
    	RotateTo和RotateBy:产生旋转效果。
    
        FadeIn::create(float d);    淡入
        FadeOut::create(float d);    淡出 
        FadeTo::create(float duration, GLubyte opacity); 一定时间内透明度变化
    	FadeIn, FadeOut和FateTo:产生淡入淡出效果,和透明变化效果。
    
        TintTo::create(float duration, GLubyte red, GLubyte green, GLubyte blue);
        TintBy::create(float duration, GLubyte red, GLubyte green, GLubyte blue);
    	TintTo和TintBy:设置色调变化,这个动作较少使用。red, green, blue的取值范围为0~255。
    
     	Blink::create(float duration, int blinks);
    	Blink:使节点闪烁,其中blinks为闪烁次数。
    
    
    复合动作类
    	DelayTime::create(float d);
    	DelayTime:延时动作其实什么都不做,提供一段空白期,d表示需要延时的时间。
    
        Repeat::create(FiniteTimeAction *action, unsigned int times);
        RepeatForever::create(ActionInterval *action);
    	Repeat/RepeatForever:反复执行某个动作。
    
        Spawn::create(FiniteTimeAction *action1, ...);
        Spawn::create(const Vector<FiniteTimeAction*>& arrayOfActions);
    	Spawn:使一批动作同时执行。
    
        Sequence::create(FiniteTimeAction *action1, ...);
        Sequence::create(const Vector<FiniteTimeAction*>& arrayOfActions);
    	Sequence:让各种动作有序执行。
    
    变速动作类
        auto repeat = RepeatForever::create(animation);
        auto speed = Speed::create(repeat, 0.5f);
        sprite->runAction(speed);
    	Speed:用于线性的改变某个动作的速度,为了改变一个动作的速度,首先需要将目标动作包装到Speed动作中,第二个参数为变速比例,设置为0.5f则速度为原来一半。
    
        auto sineIn = EaseSineIn::create(action);
        sprite->runAction(sineIn);
    	ActionEase:Speed虽然能改变动作的速度,但是只能按比例改变速度,ActionEase可以实现动作的速度又快到慢、速度随时间改变的匀速运动。该类包含5类运动,指数缓冲、Sine缓冲、弹性缓冲、跳跃缓冲和回震缓冲。每类运动都包含3个不同时期的变换:In、Out和InOut。
    

    关于动画

    序列帧动画(Animation)
    Cocos2d-x中,动画的具体内容是依靠精灵显示出来的,为了显示动态图片,我们需要不停切换精灵显示的内容,通过把静态的精灵变为动画播放器从而实现动画效果。动画由帧组成,每一帧都是一个纹理,我们可以使用一个纹理序列来创建动画。

    我们使用Animation类描述一个动画,而精灵显示动画的动作则是一个Animate对象。动画动作Animate是精灵显示动画的动作,它由一个动画对象创建,并由精灵执行。

    上面描述有点乱,我是这么理解的,真真的动画动作,其实是Animate继承了Action的子类,而Animation只是构成动画动作的资源对象。相当于剧本和道具并非实质性的演出。

    Animation的创建方法

    手动添加的方法需要将每一帧要显示的精灵有序添加到Animation类中,并设置每帧的播放时间,让动画能够匀速播放。另外,还要通过setRestoreOriginalFrame来设置是否在动画播放结束后恢复到第一帧。创建好Animation实例后,需要创建一个Animate实例来播放序列帧动画。

    	int graphics = 9;
    	// 假设一共9张图片
    	char birdframe[20];
    	Vector<SpriteFrame*> spriteFrems;
    	// 创建一个精灵帧数组
    
    	for (int i = 1; i <= graphics; i++) {
    		// 在for循环里使用sprintf拼凑出每一帧图片的文件名
    		sprintf(birdframe, "bird%d.png", i);
    		// 通过图片文件名创建精灵
    		auto birdSprite = Sprite::create(birdframe);
    		// 通过getSpriteFrame()函数把精灵转换为精灵帧,在加入到精灵帧数组里
    		spriteFrems.pushBack(birdSprite->getSpriteFrame());
    	}
    	// 根据精灵帧数组创建动画,第一个参数时精灵帧数组,第二个参数是执行每一帧花费的时间,假设这个动画0.6秒执行完,那么这个参数每帧执行的时间就是0.6/9
    	auto animaltion = Animation::createWithSpriteFrames(spriteFrems, 0.6/graphics);
    
    	// 根据动画创建动画动作
    	auto animate = Animate::create(animaltion);
    
    	// 用这个动画动作创建一个用久循环的动作
    	auto repeatAct = RepeatForever::create(animate);
    	
    	// 让需要执行这个动作的对象调用runAction()函数执行这个动画动作
    	bird->runAction(repeatAct);
    

    动画缓存

    动画缓存(AnimationCache)
    当需要加载大量动画时,可以把动画加入到动画缓存里

    	// 用精灵帧数组创建动画
    	auto animaltion = Animation::createWithSpriteFrames(spriteFrames, 0.1);
    	//把动画加入到动画缓存里第一个参数是需要加入缓存的动画,第二个参数是动画名,之后是根据这个动画名取出对应的动画
    	AnimationCache::getInstance()->addAnimation(animaltion, animationName);
    	
    	// 获得动画缓存对象 
    	auto cache = AnimationCache::getInstance();
    
    	// 从动画缓存中获得指定的动画,参数是加入缓存时addAnimation(animaltion, animationName)函数第二个参数--动画名
    	auto animation = cache->getAnimation(animationName);
    
    	// 接下来就和使用普通动画一样,根据动画来创建一个动画动作(Animate)
    	auto animate = Animate::create(animation);
    
    	// 创建一个永久循环的动作
    	auto repeatAct = RepeatForever::create(animate);
    
    	// 执行这个动画动作
    	hero->runAction(repeatAct);
    	
    	// 常用接口
    	static AnimationCache* getInstance(),全局共享的单例
    	void addAnimation(Animation *animation, const std::string& name),添加一个动画到缓存
    	void addAnimationsWithFile(const std::string& plist),添加动画文件到缓存,plist文件
    	void removeAnimation(const std::string& name),移除一个指定的动画
    	Animation* getAnimation(const std::string& name),从缓存中获取动画对象
    	建议:在内存警告时我们应该加入如下的清理缓存操作:
    
    	void releaseCaches()
    
    	{
        AnimationCache::destroyInstance();
    
        SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();
    
        TextureCache::getInstance()->removeUnuserdTextures();
    	}
    	
    	值得注意的是清理的顺序,我们推荐先清理动画缓存,然后清理精灵帧缓存,最后是纹理缓存。按照引用层级由高到低,以保证释放引用有效。
    

    骨骼动画详解-Spine

    游戏中人物的走动,跑动,攻击等动作是必不可少,实现它们的方法一般采用帧动画或者骨骼动画。帧动画的每一帧都是角色特定姿势的一个快照(完整的照片),骨骼动画则是主要将对象拆分成个各个小件(小部位),通过在每一帧中按动画要求组合这些小件。从而达到类似帧动画的快照效果,两者的区别帧动画应该每一帧都是完整的图片,所以占用内存和体积会偏大,而骨骼动画小件资源可以重复利用,每一帧之需要记录小件组合的规则,所以相对图片资源体积小,占有内存小。

    更多相关内容
  • 动画动画匀速运动加速匀速减速运动缓冲运动(在某个区间内做减速运动)封装缓冲运动的函数 动画 动画必须和定时器一起实现 匀速运动 <!DOCTYPE html> <html lang="en"> <head> <meta charset...

    运动

    动画必须和定时器一起实现

    匀速运动

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <script>
        // 获取元素
        let box = document.querySelector('.box')
        box.onclick = function () {
          let left = 0
          let timer = setInterval(function () {
            // 每次定时器移动同样的距离
            left += 13
            if (left >= 800) {
              // 固定移动的距离
              left = 800
              // 判断条件成立清除定时器
              clearInterval(timer)
            }
            box.style.left = left + 'px'
          }, 50)
        }
      </script>
    </body>
    
    </html>
    

    加速匀速

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <script>
        // 获取元素
        let box = document.querySelector('.box')
        box.onclick = function () {
          let left = 0
          let speed = 0
          let timer = setInterval(function () {
            // 开启每次定时器时,只需要移动比上一次更多的距离
            // 第一次为0 left为0 
            // 第二次为10 left 为10
            // 第三次为20 left 为10 + 20
            // 第四次为30 left 为30 + 30
            speed += 10
            left = left + speed
    
            if (left >= 800) {
              left = 800
              clearInterval(timer)
            }
            box.style.left = left + 'px'
          }, 50)
        }
      </script>
    </body>
    
    </html>
    

    减速运动

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <script>
        // 获取元素
        let box = document.querySelector('.box')
        box.onclick = function () {
          let left = 0
          let speed = 100
          let timer = setInterval(function () {
            // 开启每次定时器时,只需要移动比上一次更少的距离
            // 第一次为100 left 为 100  移动 100
            // 第二次为90  left 为 190  移动 90
            // 第三次为80  left 为 270  移动 80
            // 第四次为70  left 为 340  移动 70
            speed -= 10
            left = left + speed
    
            if (speed <= 0) {
              clearInterval(timer)
              //console.log(1)
            }
            box.style.left = left + 'px'
          }, 50)
        }
      </script>
    </body>
    
    </html>
    

    缓冲运动(在某个区间内做减速运动)

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <script>
        /*
          缓冲运动:在某个区间内做减速运动
          如果是之前的动画减速运动的话不能固定区间距离
          假如在0-800内做减速运动
          speed =(目标值 - 当前值) / 系数
          此处的目标值为设定的值,当前值为移动后的值,系数随意即可
        */
        // 获取元素
        let box = document.querySelector('.box')
        box.onclick = function () {
          let left = 0
          let speed = 0
    
          let target = 800
          let timer = setInterval(function () {
            // target-left值会越来越小,因为下一次定时器的left是变化的
            /*
              第一次执行定时器:
                target 为 800
                left   为 0
                speed  为 80
              第一次执行定时器:
                target 为 800
                left   为 0+80  80
                speed  为 (800-80)10 72
            */
            speed = Math.ceil((target - left) / 5)
            left = left + speed
            // 如果 speed = (target - left) / 5 
            // 下面的if判断并没有执行,因为存在小数点,会一直不成立,
            // 如果 speed = parseInt((target - left) / 5) 还是不成立,
            // 因为如果为 799.1 取整还是799 ,如果为799.9, 取整还是799,所以一直不等于800
            // 如果 Math.ceil((target - left) / 5)  向上取整
            // 因为如果为 799.1 向上取整是800 ,如果为799.9, 向上取整是800,所以判断成立 
            // 成立就可以执行if判断语句,并关闭定时器
            if (left === target) {
              clearInterval(timer)
            }
            box.style.left = left + 'px'
            // console.log(speed, left)
            // console.log(1)
          }, 50)
        }
      </script>
    </body>
    
    </html>
    

    封装缓冲运动的函数

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
    
        #btn {
          position: absolute;
          top: 120px;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <button id="btn">点击动画</button>
      <script>
    
        // 获取元素
        let box = document.querySelector('.box')
        let btn = document.querySelector('#btn')
    
        // 封装一个函数 来获取非行内样式
        function getStyle(ele, attr) {
          var style;
          if (ele.currentStyle) {
            //  ele.currentStyle 包含 所有css样式的对象
            // obj.attr 获取 obj的 attr的属性
            style = ele.currentStyle[attr];
          } else {
           //正常浏览器具有getComputedStyle()方法
            style = window.getComputedStyle(ele)[attr];
          }
          // 把获取的样式返回
          return style
        }
    
        // 封装一个缓冲运动 动画函数 
        // ele是元素, attr是样式, target是目标值
        function animation(ele, attr, target) {
          let speed;
          let timer = setInterval(() => {
            // getStyle(ele, attr) 返回值是带有单位的字符串
            let style = parseInt(getStyle(ele, attr))
            speed = Math.ceil((target - style) / 5)
            style = style + speed
            if (style === target) {
              // console.log(1) 判断是否关闭定时器
              clearInterval(timer)
            }
            // 这里的attr是字符串,需要用[]
            ele.style[attr] = style + 'px'
            // console.log(2) 判断是否开启定时器
          }, 50)
        }
    
    
        btn.onclick = function () {
          animation(box, 'width', 500)
        }
    
      </script>
    </body>
    
    </html>
    

    需求:当定时器全部清除完时(这里有多个定时器),让元素背景改为red

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
    
        #btn {
          position: absolute;
          top: 120px;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <button id="btn">点击动画</button>
      <script src="../js/utils.js"></script>
      <script>
        // 需求:当定时器全部清除完时,让元素背景改为red
    
        // 获取元素
        let box = document.querySelector('.box')
        let btn = document.querySelector('#btn')
    
        // 封装一个动画函数 
        function animation(ele, obj) {
          // 定义一个变量timerLen
          let timerLen = 0
          let speed;
          // 对象循环 key为对象里面的属性 left widht height
          for (let key in obj) {
            // 当每次遍历时,让timerLen加1
            timerLen++
            let timer = setInterval(() => {
              let style = parseInt(getStyle(ele, key))
              speed = Math.ceil((obj[key] - style) / 10)
              style = style + speed
              if (style === obj[key]) {
                clearInterval(timer)
                // 每清除一次定时器让timerLen减1
                timerLen--
                // 然后判断定时器是否清除完 为0 说明动画结束
                if (timerLen === 0) {
                  ele.style.background = 'red'
                }
              }
              ele.style[key] = style + 'px'
            }, 500)
          }
        }
    
        btn.onclick = function () {
          // animation(box, left, 800)
          // 当有多个样式需要动画效果时,可以定义一个对象数据
          animation(box, { left: 800, width: 400, height: 400 })
    
        }
    
      </script>
    </body>
    
    </html>
    

    在这里插入图片描述
    在这里插入图片描述

    问题

    但是会发现上面的那个封装动画有问题,当重复点击时,元素box却移动很快
    这里了解的定时器的会知道,重复点击会重新调用函数,并且重新生成多个定时器,所以导致移动同样的距离而时间变短了,就会加快元素移动,那怎么解决呢???

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>动画</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: skyblue;
          position: absolute;
          left: 0;
        }
    
        #btn {
          position: absolute;
          top: 120px;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <button id="btn">点击动画</button>
      <script src="../js/utils.js"></script>
      <script>
        // 需求:当定时器全部清除完时,让元素背景改为red
    
        // 获取元素
        let box = document.querySelector('.box')
        let btn = document.querySelector('#btn')
    
        // 封装一个动画函数 
        function animation(ele, obj, callback) {
          let timerLen = 0
          let speed;
          for (let key in obj) {
            timerLen++
            // 清除定时器 
            /* 
              let timer = 定时器
              不能定义变量来接收定时器
              如果使用变量的时候,点击的时候会创建一个函数地址
              变量在函数中是属于局部作用域,
              下一次点击的时候不能获取上一次点击时候创建的变量
              clearInterval(timer)  清除的是当前timer的值,当前的timer = undefined
    
              把定时器 给到元素的属性中
              元素是一个dom 也是一个对象,以地址的形式
              当第一个点击的时候 给dom对象对象添加了属性,
              下一次点击的时候是能获取 上一次给dom添加的属性
            */
            clearInterval(ele[key])
            // 给这个对象添加一个 left 属性,属性值为 一个定时器的空间地址
            ele[key] = setInterval(() => {
              let style = parseInt(getStyle(ele, key))
              speed = Math.ceil((obj[key] - style) / 10)
              style = style + speed
              if (style === obj[key]) {
                clearInterval(ele[key])
                // 每清除一次定时器让timerLen减1
                timerLen--
                // 然后判断定时器是否清除完 为0 说明动画结束
                if (timerLen === 0) {
                  // ele.style.background = 'red'
                  callback && callback()
                }
              }
              ele.style[key] = style + 'px'
            }, 500)
          }
        }
    
        btn.onclick = function () {
          // animation(box, left, 800)
          // 当有多个样式需要动画效果时,可以定义一个对象数据
          animation(box, { left: 800, width: 400, height: 400 }, function () {
            box.style.background = 'red'
          })
        }
    
      </script>
    </body>
    
    </html>
    

    注意:上面增加callback回调函数来操作元素,这样就不用在封装函数里面操作元素

    let timer = 定时器
    不能定义变量来接收定时器
    如果使用变量的时候,点击的时候会创建一个函数地址
    变量在函数中是属于局部作用域,
    下一次点击的时候不能获取上一次点击时候创建的变量
    clearInterval(timer) 清除的是当前timer的值,当前的timer = undefined

    把定时器 给到元素的属性中
    元素是一个dom 也是一个对象,以地址的形式
    当第一个点击的时候 给dom对象对象添加了属性,
    下一次点击的时候是能获取 上一次给dom添加的属性

    以下问题在敲代遇见的。
    在这里插入图片描述
    在这里插入图片描述

    如何让元素透明也可以运动变化

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 100px;
          height: 100px;
          background: pink;
          position: absolute;
          left: 0px;
          top: 0px;
          opacity: 0.1;
        }
      </style>
    </head>
    
    <body>
      <div class="box"></div>
      <script src="js/utils.js"></script>
      <script>
        let box = document.querySelector('.box');
        // 这里的opacity为0-100以内
        move(box, { opacity: 55 }, function () {
          alert('动画执行完成')
        })
    
    
        /* 
          运动函数: 有3个参数
          参数1:dom元素 参加动画元素
          参数2:一个对象,这个元素什么属性参加动画
          参数3:一个回调函数
        */
        function move(ele, obj, callback) {
    
          let timerLen = 0;
          for (let key in obj) {
            timerLen++
            let speed;
            clearInterval(ele[key])
            // 给这个对象添加一个 left 属性,属性值为 一个定时器的空间地址
            ele[key] = setInterval(() => {
              let style;
              // 0-1 *100 == 0-100   0.1*100 = 10
              if (key === 'opacity') {
                style = getStyle(ele, key) * 100;
              } else {
                style = parseInt(getStyle(ele, key));
              }
              // 0 - 4 = -4/5 = -0.8 向上取整 = 0
              speed = (obj[key] - style) / 5;
    
              // 如果计算出来的 speed 大于0 向上取整,如果小于0就向下取整
              speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
              style = style + speed;
    
              if (style === obj[key]) {
                clearInterval(ele[key]);
                timerLen--;
                if (timerLen === 0) {
                  // ele.style.background = 'blue';
                  // console.log(1);
                  // 短路运算 如果有callback 就执行callback,没有就不执行
                  callback && callback();
                }
              }
              if (key === 'opacity') {
                ele.style[key] = style / 100;
              } else {
                ele.style[key] = style + 'px';
              }
            }, 60)
          }
    
        }
      </script>
    </body>
    
    </html>
    

    圆周运动

    • 圆周运动
      • Math.cos(弧度)
      • 余弦(cos):邻边比斜边 cosA = b / 半径 b = 半径 * cos(弧度)
      • Math.sin(弧度)
      • 正弦(sin):对边比斜边 sinA = a / 半径 a = 半径 * sin(弧度)
      • 弧长 = (角度 * Math.PI) / 180°
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .box {
          width: 300px;
          height: 300px;
          border: 2px solid red;
          border-radius: 50%;
          position: absolute;
          top: 0px;
          left: 0px;
          bottom: 0px;
          right: 0px;
          margin: auto;
        }
    
        .box1 {
          width: 30px;
          height: 30px;
          background: pink;
          border-radius: 50%;
          position: absolute;
        }
      </style>
    </head>
    
    <body>
      <div class="box">
        <div class="box1"></div>
      </div>
      <script>
        let box = document.querySelector('.box');
        let box1 = document.querySelector('.box1');
        // 求大盒子的半径
        let boxR = box.offsetWidth / 2;
        // 求小盒子的半径
        let box1R = box1.offsetWidth / 2;
    
        let deg = 0;
        render()
        setInterval(() => {
          deg += 10;
          render()
        }, 50)
    
        function render() {
          // 给box1定位
          // 弧度 = (角度 * Math.PI) / 180 
          let hudu = (deg * Math.PI) / 180;
          // 求邻边和对边
          // a为对边
          let a = Math.sin(hudu) * boxR;
          // b为领边
          let b = Math.cos(hudu) * boxR;
    
          box1.style.left = b + boxR - box1R + 'px';
          box1.style.top = a + boxR - box1R + 'px';
        }
      </script>
    </body>
    
    </html>
    

    封装动画函数(可调用动画函数)

    /* 
        运动函数: 有3个参数
        参数1:dom元素 参加动画元素
        参数2:一个对象,这个元素什么属性参加动画
        参数3:一个回调函数
        注意:opacity的值 为0-100以内
        getStyle()调用获取元素的样式函数
    */
    function move(ele, obj, callback) {
    
      let timerLen = 0;
      //当里面有多个属性时,用对象遍历的方法
      for (let key in obj) {
        timerLen++
        let speed;
        clearInterval(ele[key])
        // 给这个对象添加一个 left 属性,属性值为 一个定时器的空间地址
        ele[key] = setInterval(() => {
          let style;
          // 0-1 *100 == 0-100   0.1*100 = 10
          if (key === 'opacity') {
            style = getStyle(ele, key) * 100;
          } else {
            style = parseInt(getStyle(ele, key));
          }
          // 0 - 4 = -4/5 = -0.8 向上取整 = 0
          speed = (obj[key] - style) / 5;
    
          // 如果计算出来的 speed 大于0 向上取整,如果小于0就向下取整
          speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
          style = style + speed;
    
          if (key === 'opacity') {
            ele.style[key] = style / 100;
          } else {
            ele.style[key] = style + 'px';
          }
    
          // 如果先执行回调函数 再给 元素设置 样式,会先把回调函数中的 
          // 所有 代码执行完成之后再执行后面代码
          if (style === obj[key]) {
            clearInterval(ele[key]);
            timerLen--;
            if (timerLen === 0) {
              // 短路运算 如果有callback 就执行callback,没有就不执行
              callback && callback();
            }
          }
    
          // 轮播图的时候注意:当时间 为60的时候,30次 1800毫秒 才能把内层的定时器执行完成
          // 外层的定时器 是1300毫秒执行一次,会造成的问题就是 内层的定时器还没有执行完成 外层定时器有重新执行了
    
        }, 30)
      }
    }
    
       // 封装一个函数 来获取非行内样式
        function getStyle(ele, attr) {
          var style;
          if (ele.currentStyle) {
            //  ele.currentStyle 包含 所有css样式的对象
            // obj.attr 获取 obj的 attr的属性
            style = ele.currentStyle[attr];
          } else {
           //正常浏览器具有getComputedStyle()方法
            style = window.getComputedStyle(ele)[attr];
          }
          // 把获取的样式返回
          return style
        }
        
    

    轮播图效果(第一种方法)

    animation.js文件

    /*
    
         引用狗哥封装函数注释和解析
    
    */
    
    //动画:animation(ele, obj, callback)
    //参数1:为需要运动的元素 ; 参数2:为元素的属性的修改,以对象的形式(注意点:透明度设置为0.5  则需要0.5 * 100)
    //参数3:为回调函数,就是待动画执行完毕后,需要操作
    function animation(ele, obj, callback) {
    
      let timerLen = 0; //定时器的执行次数
      //遍历对象obj 进行动画样式的设置!
      for (let key in obj) {
        timerLen++
        // console.log(key); //字符串的格式 key --属性 top等等
        // console.log(obj[key]); //也就是目标值 属性值  obj[key] 100
        //style就是所运动的样式
        clearInterval(ele[key]) //清除上一次的定时器
    
        let speed = 0; //速度
        ele[key] = setInterval(() => {
    
          //假如为透明属性的时候,就获取到初始的透明值,否则就是获取当前样式的属性!
          if (key === "opacity") {
            //属性值的初始设置为小于1的,为透明度的时候 值需要*100,为了方便计算!
            style = getStyle(ele, key) * 100 //拿到初始的属性值 
          } else {
            var style = parseInt(getStyle(ele, key)); //获取到非行内样式  
          }
          //速度的计算! (目标值 - 当前样式值)/5
          speed = (obj[key] - style) / 5;
    
          //假如速度小于0的时候,就是代表负数,向下取整(负数)
          speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
          style = style + speed //所修改的样式 = 当前样式 + 速度
    
          // console.log(style, obj[key]); //50 100
          if (key === "opacity") { //由于透明属性没有那个单位,因此需要判断!
            ele.style[key] = style / 100 //修改ele元素的样式
          } else {
            ele.style[key] = style + "px" //修改ele元素的样式
          }
    
          if (style === obj[key]) { //当left等于目标值的之后,就清除定时器!
            clearInterval(ele[key])
            timerLen-- //执行完定时器后,就定时器计数渐渐 当定时器计数器为0的时候,代表动画执行结束
            if (timerLen === 0) {
              // console.log("动画执行完毕了");
              callback()
            }
          }
        }, 30)
      }
    }
    
    
    
    //封装一个获取非行内样式的函数  --- getStyle(box, 'height')
    //参数1:为需要获取的元素,参数2:为获取元素的属性(需要添加'')  返回值:为style
    function getStyle(ele, attr) {
      var style;
      if (ele.currentStyle) {
        // ele.currentStyle 包含 所有css样式的对象 需要使用obj['属性']
        style = ele.currentStyle[attr]
      } else {
        style = window.getComputedStyle(ele)[attr]
      }
      return style
    }
    

    html代码

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <style>
        * {
          padding: 0;
          margin: 0;
        }
    
        ul,
        li {
          list-style: none;
        }
    
        .box {
          width: 600px;
          height: 300px;
          border: 2px solid #ccc;
          position: relative;
          margin: auto;
          margin-top: 100px;
          overflow: hidden;
        }
    
        .box .imgBox {
          width: 500%;
          height: 300px;
          display: flex;
          position: absolute;
          left: -600px;
        }
    
        .box .imgBox li {
          width: 600px;
          height: 300px;
          display: flex;
          justify-content: center;
          align-items: center;
          font-size: 50px;
          font-weight: 900;
          color: #fff;
          flex-shrink: 0;
        }
    
        .box .pointBox {
          height: 20px;
          position: absolute;
          bottom: 30px;
          right: 20px;
          display: flex;
          justify-content: space-evenly;
          align-items: center;
          border-radius: 10px;
        }
    
        .box .pointBox li {
          width: 25px;
          height: 25px;
          background: rgba(0, 0, 0, .4);
          border-radius: 50%;
          cursor: pointer;
          color: #fff;
          display: flex;
          justify-content: center;
          align-items: center;
          margin-right: 5px;
    
        }
    
        .box .pointBox li.active {
          background: rgba(255, 255, 0, .5);
        }
    
        .box .leftRightTabs {
          position: absolute;
          top: 50%;
          width: 100%;
          transform: translateY(-50%);
          display: flex;
          justify-content: space-between;
        }
    
        .box .leftRightTabs span {
          width: 40px;
          height: 40px;
          color: #fff;
          font-size: 30px;
          cursor: pointer;
          user-select: none;
          background: rgba(0, 0, 0, .4);
          display: flex;
          justify-content: center;
          align-items: center;
        }
    
        .box .leftRightTabs span:nth-child(1) {
          border-radius: 0 50% 50% 0;
        }
    
        .box .leftRightTabs span:nth-child(2) {
          border-radius: 50% 0 0 50%;
        }
      </style>
      <script src="./js/animation.js"></script>
    </head>
    
    <body>
      <div class="box">
        <ul class="imgBox">
          <li style="background: pink;">1</li>
          <li style="background: green;">2</li>
          <li style="background: blue;">3</li>
          <li style="background: purple;">4</li>
          <li style="background: red;">5</li>
        </ul>
        <!-- 小圆点 -->
        <ul class="pointBox"></ul>
        <!-- 左右切换 -->
        <div class="leftRightTabs">
          <span class="left">&lt;</span>
          <span class="right">&gt;</span>
        </div>
      </div>
    
      <script>
        /* 
          1. 获取元素
          2. 设置焦点,根据 imgBox 里面 li 的个数设置焦点
          3. 复制元素,第一个元素复制出来放在末尾,最后一只复制出来放在头
          4. 自动轮播,搞一个定时器,每隔多少时间 index++ 动一下
          5. 移入移出,移入的时候停掉 autoLoop
          6. 点击左右按钮切换
          7. 点击焦点切换
              + 要拿到点击的哪个焦点的 索引
              + 可不可以在setPoint 的时候保存一个索引在 li 身上
              + 点每一个 li 的时候拿到身上的属性就可以了            
        */
    
        window.onload = function () {
          // 获取imgBox元素
          let imgBox = document.querySelector('.imgBox');
          // 获取imgBox下的所有子元素
          let list = imgBox.children;
    
          // 获取小圆点元素的父元素
          let pointBox = document.querySelector('.pointBox');
          // 获取整个div 元素
          let box = document.querySelector('.box');
          // 获取盒子的宽度 此处为600
          let boxWidth = box.clientWidth;
    
          // 获取左右切换元素的父元素
          let leftRightTabs = document.querySelector('.leftRightTabs');
          // 设置一个变量为true 用于左右切换
          let loopFlag = true;
    
          // 渲染数据 设置焦点的(小圆点)
          setPoint(list, pointBox)
    
          // 克隆第一张和最后一个元素(需要在渲染完小圆点数据之后操作)
          let copyFirst = imgBox.firstElementChild.cloneNode(true);
          let copyLast = imgBox.lastElementChild.cloneNode(true);
          imgBox.appendChild(copyFirst); //把赋值出来的第一张添加在imgBox的最后面
          imgBox.insertBefore(copyLast, imgBox.firstElementChild);//把赋值出来的最后一张添加在imgBox的第一张前面
    
          imgBox.style.width = boxWidth * imgBox.children.length + 'px';//把装轮播图的容器的宽度变大
    
    
          // 轮播图运动起来
          let index = 1;
          // 定义一个定时器变量
          let timer;
          // 自动播放
          autoPlay()
    
          // 鼠标滑过时候清除定时器,停止播放
          box.addEventListener('mouseover', () => clearInterval(timer))
          // 鼠标移出的时候重新调用函数,再重新播放
          box.addEventListener('mouseout', () => autoPlay())
    
          // 封装一个设置小圆点的函数
          function setPoint(arr, pointBox) {
            // 排他思想,清除所有的小圆点样式
            for (let i = 0; i < arr.length; i++) {
              let li = document.createElement('li');
              // 当是第一个点的时候,给这个点设置class名为 active
              if (i === 0) {
                li.classList.add('active')
              }
              // 显示小圆点里面的内容
              li.innerHTML = i + 1;
              // 自定义属性 属性值为索引值
              li.setAttribute('point-index', i)
              // 添加到 父元素 pointBox 里面
              pointBox.appendChild(li);
            }
          }
    
          // 自动播放函数
          function autoPlay() {
            timer = setInterval(() => {
              index++;
              // 调用动画函数 imgbox 元素,向右运动,回调函数 moveEnd
              animation(imgBox, { left: -index * 600 }, moveEnd);
            }, 2000)
          }
    
          // 运动结束之后操作的事情 moveEnd函数
          function moveEnd() {
            // 当index为轮播图循环完之后的长度减1时,当index为6,重新从第二张开始
            // console.log(imgBox.children.length) // 7 
            // console.log(index) // 从2开始打印
            if (index === imgBox.children.length - 1) {
              index = 1;
              // 向右移动的距离
              imgBox.style.left = -index * boxWidth + 'px';
            }
            // 多判断一下,当index === 0
            if (index === 0) {
              index = imgBox.children.length - 2;
              imgBox.style.left = -index * boxWidth + 'px';
            };
            // 判断小圆点的样式,清除所有的样式
            for (let i = 0; i < pointBox.children.length; i++) {
              pointBox.children[i].classList.remove('active');
            };
            // 给当前的小圆点添加样式
            pointBox.children[index - 1].classList.add('active');
            // 让loopflag改为true
            loopFlag = true;
          }
    
          // 点击左右按钮的时候,切换轮播图
          // 委托给左右切换的父元素绑定事件
          leftRightTabs.addEventListener('click', e => {
            // 判断点击事件,如果为false,结束点击事件,防止开启多个动画,也就是开启多个定时器
            if (loopFlag === false) {
              return
            };
            // 如果不是false,先改变这个值为false
            loopFlag = false;
            if (e.target.className === 'left') {
              index--;
              // console.log(index) //打印 1 0 4 3 2
              animation(imgBox, { left: -index * 600 }, moveEnd);
            } else if (e.target.className === 'right') {
              index++;
              // console.log(index) //打印 6 2 3 4 5
              animation(imgBox, { left: -index * 600 }, moveEnd);
            }
          })
    
          // 点击小圆点的时候也可以切换图片
          // 委托给小圆点的父元素绑定事件 
          pointBox.addEventListener('click', e => {
            // 判断点击事件,如果为false,结束点击事件,防止开启多个动画,也就是开启多个定时器
            if (loopFlag === false) {
              return
            };
            // 如果不是false,先改变这个值为false
            loopFlag = false;
            // 判断选中是否为li
            if (e.target.tagName === 'LI') {
              // console.log(e.target.getAttribute('point-index')) //打印的是字符串 需要转为数值型 - 0
              index = e.target.getAttribute('point-index') - 0 + 1
              // console.log(index) //打印 1 2 3 4 5
              animation(imgBox, { left: -index * boxWidth }, moveEnd)
            }
          })
        }
      </script>
    </body>
    
    </html>
    

    轮播图效果(第二种方法)

    轮播图index.js

    window.addEventListener('load', function () {
      // 1. 获取元素
      var arrow_l = document.querySelector('.arrow-l');
      var arrow_r = document.querySelector('.arrow-r');
      var focus = document.querySelector('.focus');
      var focusWidth = focus.offsetWidth;
      // 2. 鼠标经过focus 就显示隐藏左右按钮
      focus.addEventListener('mouseenter', function () {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);
        timer = null; // 清除定时器变量
      });
      focus.addEventListener('mouseleave', function () {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function () {
          //手动调用点击事件
          arrow_r.click();
        }, 2000);
      });
    
      // 3. 动态生成小圆圈  有几张图片,我就生成几个小圆圈
      var ul = focus.querySelector('ul');
      var ol = focus.querySelector('.circle');
      // console.log(ul.children.length);
      for (var i = 0; i < ul.children.length; i++) {
        // 创建一个小li 
        var li = document.createElement('li');
        // 记录当前小圆圈的索引号 通过自定义属性来做 
        li.setAttribute('index', i);
        // 把小li插入到ol 里面
        ol.appendChild(li);
        // 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
        li.addEventListener('click', function () {
          // 干掉所有人 把所有的小li 清除 current 类名
          for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
          }
          // 留下我自己  当前的小li 设置current 类名
          this.className = 'current';
          // 5. 点击小圆圈,移动图片 当然移动的是 ul 
          // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
          // 当我们点击了某个小li 就拿到当前小li 的索引号
          var index = this.getAttribute('index');
          // 当我们点击了某个小li 就要把这个li 的索引号给 num  
          num = index;
          // 当我们点击了某个小li 就要把这个li 的索引号给 circle  
          circle = index;
          // num = circle = index;
          console.log(focusWidth);
          console.log(index);
    
          animate(ul, -index * focusWidth);
        })
      }
    
      // 把ol里面的第一个小li设置类名为 current
      ol.children[0].className = 'current';
      // 6. 克隆第一张图片(li)放到ul 最后面
      var first = ul.children[0].cloneNode(true);
      ul.appendChild(first);
      // 7. 点击右侧按钮, 图片滚动一张
      var num = 0;
      // circle 控制小圆圈的播放
      var circle = 0;
      // flag 节流阀
      var flag = true;
      arrow_r.addEventListener('click', function () {
        if (flag) {
          flag = false; // 关闭节流阀
          // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
          if (num == ul.children.length - 1) {
            ul.style.left = 0;
            num = 0;
          }
          num++;
          animate(ul, -num * focusWidth, function () {
            flag = true; // 打开节流阀
          });
          // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
          circle++;
          // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原
          if (circle == ol.children.length) {
            circle = 0;
          }
          // 调用函数
          circleChange();
        }
      });
    
      // 9. 左侧按钮做法
      arrow_l.addEventListener('click', function () {
        if (flag) {
          flag = false;
          if (num == 0) {
            num = ul.children.length - 1;
            ul.style.left = -num * focusWidth + 'px';
          }
          num--;
          animate(ul, -num * focusWidth, function () {
            flag = true;
          });
          // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
          circle--;
          // 如果circle < 0  说明第一张图片,则小圆圈要改为第4个小圆圈(3)
          // if (circle < 0) {
          //     circle = ol.children.length - 1;
          // }
          circle = circle < 0 ? ol.children.length - 1 : circle;
          // 调用函数
          circleChange();
        }
      });
    
      function circleChange() {
        // 先清除其余小圆圈的current类名
        for (var i = 0; i < ol.children.length; i++) {
          ol.children[i].className = '';
        }
        // 留下当前的小圆圈的current类名
        ol.children[circle].className = 'current';
      }
    
      
      // 10. 自动播放轮播图
      var timer = setInterval(function () {
        //手动调用点击事件
        arrow_r.click();
      }, 2000);
    })
    

    动画函数封装(注意不同于之前的另一种封装)
    animate.js

    function animate(obj, target, callback) {
      // console.log(callback);  callback = function() {}  调用的时候 callback()
    
      // 先清除以前的定时器,只保留当前的一个定时器执行
      clearInterval(obj.timer);
      obj.timer = setInterval(function () {
        // 步长值写到定时器的里面
        // 把我们步长值改为整数 不要出现小数的问题
        // var step = Math.ceil((target - obj.offsetLeft) / 10);
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
          // 停止动画 本质是停止定时器
          clearInterval(obj.timer);
          // 回调函数写到定时器结束里面
          // if (callback) {
          //     // 调用函数
          //     callback();
          // }
          callback && callback();
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';
      }, 15);
    }
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <link rel="stylesheet" href="./index.css">
      <style>
        * {
          padding: 0;
          margin: 0;
        }
    
        a {
          text-decoration: none;
        }
    
        ul,
        ol,
        li {
          list-style: none;
        }
      </style>
    </head>
    
    <body>
      <div class="focus fl">
        <!-- 左侧按钮 -->
        <a href="javascript:;" class="arrow-l">
          &lt;
        </a>
        <!-- 右侧按钮 -->
        <a href="javascript:;" class="arrow-r"> &gt; </a>
        <!-- 核心的滚动区域 -->
        <ul>
          <li>
            <a href="#"><img src="img/focus.jpg" alt=""></a>
          </li>
          <li>
            <a href="#"><img src="img/focus1.jpg" alt=""></a>
          </li>
          <li>
            <a href="#"><img src="img/focus2.jpg" alt=""></a>
          </li>
          <li>
            <a href="#"><img src="img/focus3.jpg" alt=""></a>
          </li>
        </ul>
        <!-- 小圆圈 -->
        <ol class="circle">
    
        </ol>
      </div>
      <script src="./js/animate.js"></script>
      <script src="./js/index.js"></script>
    </body>
    
    </html>
    

    index.css样式

    @charset "uft-8";
    
    .focus {
      position: relative;
      width: 721px;
      height: 455px;
      background-color: purple;
      overflow: hidden;
      margin: 0 auto;
    }
    
    .focus ul {
      position: absolute;
      top: 0;
      left: 0;
      width: 600%;
    }
    
    .focus ul li {
      float: left;
    }
    
    .arrow-l,
    .arrow-r {
      display: none;
      position: absolute;
      top: 50%;
      margin-top: -20px;
      width: 24px;
      height: 40px;
      background: rgba(0, 0, 0, .3);
      text-align: center;
      line-height: 40px;
      color: #fff;
      font-family: 'icomoon';
      font-size: 18px;
      z-index: 2;
    }
    
    .arrow-r {
      right: 0;
    }
    
    .circle {
      position: absolute;
      bottom: 10px;
      left: 50px;
    }
    
    .circle li {
      float: left;
      width: 8px;
      height: 8px;
      /*background-color: #fff;*/
      border: 2px solid rgba(255, 255, 255, 0.5);
      margin: 0 3px;
      border-radius: 50%;
      /*鼠标经过显示小手*/
      cursor: pointer;
    }
    
    .current {
      background-color: #fff;
    }
    

    导航栏筋斗云效果

    <!DOCTYPE html>
    <html>
    
    <head lang="en">
      <meta charset="UTF-8">
      <title></title>
      <style>
        * {
          margin: 0;
          padding: 0
        }
    
        ul {
          list-style: none;
        }
    
        body {
          background-color: black;
        }
    
        .c-nav {
          width: 900px;
          height: 42px;
          background: #fff url(images/rss.png) no-repeat right center;
          margin: 100px auto;
          border-radius: 5px;
          position: relative;
        }
    
        .c-nav ul {
          position: absolute;
        }
    
        .c-nav li {
          float: left;
          width: 83px;
          text-align: center;
          line-height: 42px;
        }
    
        .c-nav li a {
          color: #333;
          text-decoration: none;
          display: inline-block;
          height: 42px;
        }
    
        .c-nav li a:hover {
          color: white;
        }
    
        .c-nav li.current a {
          color: #0dff1d;
        }
    
        .cloud {
          position: absolute;
          left: 0;
          top: 0;
          width: 83px;
          height: 42px;
          background: url(images/cloud.gif) no-repeat;
        }
      </style>
    
      <script>
        window.addEventListener('load', function () {
          // 1. 获取元素
          var cloud = document.querySelector('.cloud');
          var c_nav = document.querySelector('.c-nav');
          var lis = c_nav.querySelectorAll('li');
          // 2. 给所有的小li绑定事件 
          // 这个current 做为筋斗云的起始位置
          var current = 0;
          for (var i = 0; i < lis.length; i++) {
            // (1) 鼠标经过把当前小li 的位置做为目标值
            lis[i].addEventListener('mouseenter', function () {
              animate(cloud, this.offsetLeft);
            });
            // (2) 鼠标离开就回到起始的位置 
            lis[i].addEventListener('mouseleave', function () {
              animate(cloud, current);
            });
            // (3) 当我们鼠标点击,就把当前位置做为目标值
            lis[i].addEventListener('click', function () {
              current = this.offsetLeft;
            });
          }
        })
    
        // 动画函数
        function animate(obj, target, callback) {
          // console.log(callback);  callback = function() {}  调用的时候 callback()
          // 先清除以前的定时器,只保留当前的一个定时器执行
          clearInterval(obj.timer);
          obj.timer = setInterval(function () {
            // 步长值写到定时器的里面
            // 把我们步长值改为整数 不要出现小数的问题
            // var step = Math.ceil((target - obj.offsetLeft) / 10);
            var step = (target - obj.offsetLeft) / 10;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            if (obj.offsetLeft == target) {
              // 停止动画 本质是停止定时器
              clearInterval(obj.timer);
              // 回调函数写到定时器结束里面
              // if (callback) {
              //     // 调用函数
              //     callback();
              // }
              callback && callback();
            }
            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
            obj.style.left = obj.offsetLeft + step + 'px';
          }, 15);
        }
    
      </script>
    </head>
    
    <body>
      <div id="c_nav" class="c-nav">
        <span class="cloud"></span>
        <ul>
          <li class="current"><a href="#">首页新闻</a></li>
          <li><a href="#">师资力量</a></li>
          <li><a href="#">活动策划</a></li>
          <li><a href="#">企业文化</a></li>
          <li><a href="#">招聘信息</a></li>
          <li><a href="#">公司简介</a></li>
          <li><a href="#">我是佩奇</a></li>
          <li><a href="#">啥是佩奇</a></li>
        </ul>
      </div>
    </body>
    
    </html>
    
    展开全文
  • 3DMAX,自己制作的角色走路+跑步+疾跑+缓冲动作制作 勿商用
  • Flash格斗动画动作设计和动作的制作2007-11-01 23:00:42 来源:闪吧 justsolo■第一课:理论基础 首先我们要先确立对象,我们的对象是格斗的动作设计,以及动作动画制作,不需要多余的场景,不需要多余的噱头,把握好...
  • 缓冲系统,动作系统,计时器前言一、缓冲系统二、动作系统三,计时器总结 前言 官网官网!!! cc.tween 能够对对象的任意属性进行缓动,功能类似于 cc.Action(动作系统)。但是 cc.tween 会比 cc.Action 更加简洁...

    Cocos Creator系列文章目录

    Cocos Creator–1.介绍

    Cocos Creator-2.UI系统

    Cocos Creator-3.缓冲系统,动作系统,计时器

    Cocos Creator-4.监听,发射事件,节点系统事件,全局系统事件

    Cocos Creator-5.物理与碰撞系统

    Cocos Creator-6.TS-属性检查器


    # 前言 [官网官网!!!](https://docs.cocos.com/creator/manual/zh/scripting/tween.html) cc.tween 能够对对象的任意属性进行缓动,功能类似于 cc.Action(动作系统)。但是 cc.tween 会比 cc.Action 更加简洁易用,因为 cc.tween 提供了链式创建的方法,可以对任何对象进行操作,并且可以对对象的任意属性进行缓动。

    一、缓冲系统

    Easing_API
    Easing函数效果演示
    下面是官方的案例(其实还是很好理解的!!)

    //同时执行多个属性
    cc.tween(this.node)
        // 同时对 scale, position, rotation 三个属性缓动
        .to(1, { scale: 2, position: cc.v2(100, 100), rotation: 90 })
        .start()
    
    //支持缓动任意对象的任意属性
    let obj = { a: 0 }
    cc.tween(obj)
      .to(1, { a: 100 })
      .start()
    
    //cc.tween 提供了两个设置属性的 API:to//by
    cc.tween(node)
      .to(1, {scale: 2})      //duration:1s, node.scale === 2
      .by(1, {scale: 2})      // node.scale === 4 (2 + 2)
      .by(1, {scale: 1})      // node.scale === 5
      .to(1, {scale: 2})      // node.scale === 2
      .start()
    
    //easing使用 easing 来使缓动更生动(就是行动的方式)
    // 传入 easing 名字,直接使用内置 easing 函数
    cc.tween().to(1, { scale: 2 }, { easing: 'sineOutIn'})
    
    // 使用自定义 easing 函数
    cc.tween().to(1, { scale: 2 }, { easing: t => t*t; })
    
    // 只对单个属性使用 easing 函数
    // value 必须与 easing 或者 progress 配合使用
    cc.tween().to(1, { scale: 2, position: { value: cc.v3(100, 100, 100), easing: 'sineOutIn' } })
    
    // 对所有属性自定义 progress
    cc.tween().to(1, { scale: 2, rotation: 90 }, {
      progress: (start, end, current, ratio) => {
        return start + (end - start) * ratio;
      }
    })
    
    // 对单个属性自定义 progress
    cc.tween().to(1, {
      scale: 2,
      position: {
        value: cc.v3(),
        progress: (start, end, current, t) => {
          // 注意,传入的属性为 cc.Vec3,所以需要使用 Vec3.lerp 进行插值计算
          return start.lerp(end, t, current);
        }
      }
    })
    
    //clone 函数会克隆一个当前的缓动,并接受一个 target 作为参数。
    // 先创建一个缓动作为模板
    let tween = cc.tween().to(4, { scale: 2 })
    
    // 复制 tween,并使用节点 Canvas/cocos 作为 target
    tween.clone(cc.find('Canvas/cocos')).start()
    // 复制 tween,并使用节点 Canvas/cocos2 作为 target
    tween.clone(cc.find('Canvas/cocos2')).start()
    
    //*******重点********
    //插入其他的缓动到队列中
    let scale = cc.tween().to(1, { scale: 2 })
    let rotate = cc.tween().to(1, { rotation: 90})
    let move = cc.tween().to(1, { position: cc.v3(100, 100, 100)})
    
    // 先缩放再旋转
    cc.tween(this.node).then(scale).then(rotate)
    // 先缩放再移动
    cc.tween(this.node).then(scale).then(move)
    
    //并行执行缓动
    //cc.tween 在链式执行时是按照 sequence 的方式来执行的,但是在编写复杂缓动的时候可能会需要同时并行执行多个队列,cc.tween 提供了 parallel 接口来满足这个需求。
    let t = cc.tween;
    t(this.node)
        // 同时执行两个 cc.tween
        .parallel(
            t().to(1, { scale: 2 }),
            t().to(2, { position: cc.v2(100, 100) })
        )
        .call(() => {
            console.log('All tweens finished.')
        })
        .start()
    
    //重复执行
    //repeat/repeatForever 函数会将前一个 action 作为作用对象。但是如果有参数提供了其他的 action 或者 tween,则 repeat/repeatForever 函数会将传入的 action 或者 tween 作为作用对象。
    cc.tween(this.node)
        .by(1, { scale: 1 })
        // 对前一个 by 重复执行 10次
        .repeat(10)
        // 最后 node.scale === 11
        .start()
    
    // 也可以这样用
    cc.tween(this.node)
        .repeat(10,
            cc.tween().by(1, { scale: 1 })
        )
        .start()
    
    // 一直重复执行下去
    cc.tween(this.node)
        .by(1, { scale: 1 })
        .repeatForever()
        .start()
        
    //延迟执行
    cc.tween(this.node)
        // 延迟 1s
        .delay(1)
        .to(1, { scale: 2 })
        // 再延迟 1s
        .delay(1)
        .to(1, { scale: 3 })
        .start()
    

    二、动作系统

    动作系统 API 列表
    (动作系统目前已不推荐使用,未来将逐步移除,建议使用 缓动系统 做为替代。)
    动作系统可以在一定时间内对节点完成位移,缩放,旋转等各种动作。

    //动作系统的使用方式也很简单,在 cc.Node 中支持如下 API:
    // 创建一个移动动作
    var action = cc.moveTo(2, 100, 100);
    // 执行动作
    node.runAction(action);
    // 停止一个动作
    node.stopAction(action);
    // 停止所有动作
    node.stopAllActions();
    
    //开发者还可以给动作设置 tag,并通过 tag 来控制动作。
    // 给 action 设置 tag
    var ACTION_TAG = 1;
    action.setTag(ACTION_TAG);
    // 通过 tag 获取 action
    node.getActionByTag(ACTION_TAG);
    // 通过 tag 停止一个动作
    node.stopActionByTag(ACTION_TAG);
    
    //容器动作
    //1.顺序动作 cc.sequence 顺序动作可以让一系列子动作按顺序一个个执行。示例:
     // 让节点左右来回移动
     var seq = cc.sequence(cc.moveBy(0.5, 200, 0), cc.moveBy(0.5, -200, 0));
     node.runAction(seq);
     //2.同步动作 cc.spawn 同步动作可以同步执行对一系列子动作,子动作的执行结果会叠加起来修改节点的属性。示例:
      // 让节点在向上移动的同时缩放
     var spawn = cc.spawn(cc.moveBy(0.5, 0, 50), cc.scaleTo(0.5, 0.8, 1.4));
     node.runAction(spawn);
     //3.重复动作 cc.repeat 重复动作用来多次重复一个动作。示例:
     // 让节点左右来回移动,并重复 5 次
     var seq = cc.repeat(
                 cc.sequence(
                     cc.moveBy(2, 200, 0),
                     cc.moveBy(2, -200, 0)
                 ), 5);
     node.runAction(seq);
     //4.永远重复动作 cc.repeatForever 顾名思义,这个动作容器可以让目标动作一直重复,直到手动停止。
      // 让节点左右来回移动并一直重复
     var seq = cc.repeatForever(
                 cc.sequence(
                     cc.moveBy(2, 200, 0),
                     cc.moveBy(2, -200, 0)
                 ));
     //5.速度动作 cc.speed 速度动作可以改变目标动作的执行速率,让动作更快或者更慢完成。
      // 让目标动作速度加快一倍,相当于原本 2 秒的动作在 1 秒内完成
     var action = cc.speed(
                     cc.spawn(
                         cc.moveBy(2, 0, 50),
                         cc.scaleTo(2, 0.8, 1.4)
                     ), 2);
     node.runAction(action);
     //6.我们给容器类型动作提供了更为方便的链式 API,动作对象支持以下三个 API:repeat、repeatForever、speed,这些 API 都会返回动作对象本身,支持继续链式调用。我们来看一个更复杂的动作示例:
     // 一个复杂的跳跃动画
    this.jumpAction = cc.sequence(
        cc.spawn(
            cc.scaleTo(0.1, 0.8, 1.2),
            cc.moveTo(0.1, 0, 10)
        ),
        cc.spawn(
            cc.scaleTo(0.2, 1, 1),
            cc.moveTo(0.2, 0, 0)
        ),
        cc.delayTime(0.5),
        cc.spawn(
            cc.scaleTo(0.1, 1.2, 0.8),
            cc.moveTo(0.1, 0, -10)
        ),
        cc.spawn(
            cc.scaleTo(0.2, 1, 1),
            cc.moveTo(0.2, 0, 0)
        )
    // 以 1/2 的速度慢放动画,并重复 5 次
    ).speed(2).repeat(5);
    
    
    //动作回调(得好好理解)
    //动作回调可以用以下的方式声明:
    //第一个参数是处理回调的方法,第二个参数指定了处理回调方法的 context(也就是绑定 this),第三个参数是向处理回调方法的传参
    var finished = cc.callFunc(this.myMethod, this, opt);
    //可以这样使用传参:
    var finished = cc.callFunc(function(target, score) {
        this.score += score;
    }, this, 100); //动作完成后会给玩家加 100 分
    
    //在声明了回调动作 finished 后,您可以配合 cc.sequence 来执行一整串动作并触发回调:
    var myAction = cc.sequence(cc.moveBy(1, cc.v2(0, 100)), cc.fadeOut(1), finished);
    ///***注意:在 cc.callFunc 中不应该停止自身动作,由于动作是不能被立即删除,如果在动作回调中暂停自身动作会引发一系列遍历问题,导致更严重的 bug。
    
    //缓动动作
    var action = cc.scaleTo(0.5, 2, 2);
    action.easing(cc.easeIn(3.0));
    

    基础的缓动动作类cc.ActionEase


    三,计时器

    cc.Scheduler,主要的API!!
    注意:cc.Node 不包含计时器相关
    Component API
    关于计时器的函数:

    • schedule:开始一个计时器
    • scheduleOnce:开始一个只执行一次的计时器
    • unschedule:取消一个计时器
    • unscheduleAllCallbacks:取消这个组件的所有计时器
    //首先,先创建一个指向某个组件的变量,变量名为 component。
    //1.开始一个计时器,,首先,先创建一个指向某个组件的变量,变量名为 component。计时器将每隔 5s 执行一次。
     component.schedule(function() {
         // 这里的 this 指向 component
         this.doSomething();
     }, 5);
     
     //2.更灵活的计时器计时器将在 10 秒后开始计时,每 5 秒执行一次回调,执行 3 + 1 次。
     // 以秒为单位的时间间隔
     var interval = 5;
     // 重复次数
     var repeat = 3;
     // 开始延时
     var delay = 10;
     component.schedule(function() {
         // 这里的 this 指向 component
         this.doSomething();
     }, interval, repeat, delay);
     
     //3.只执行一次的计时器(快捷方式),上面的计时器将在两秒后执行一次回调函数,之后就停止计时。
     component.scheduleOnce(function() {
         // 这里的 this 指向 component
         this.doSomething();
     }, 2);
     
     //4.取消计时器
     this.count = 0;
     this.callback = function () {
         if (this.count === 5) {
             // 在第六次执行回调时取消这个计时器
             this.unschedule(this.callback);
         }
         this.doSomething();
         this.count++;
     }
     component.schedule(this.callback, 1);
     
    

    总结

    是十分值得学习,以后还要更新的!!!

    展开全文
  • 随着Rich Internet ...前文我们学习了Blend设计简单的动画,可以使用StoryBoard快速创建一个动画效果,但是该动画效果看起来缺乏自然效果,让用户感觉太过机械化,大大的降低了用户体验性。为了是动画更为人性化...

    随着Rich Internet application(RIA)应用技术的发展,各个公司越来越注重于项目的用户体验性,在保证其功能完善,运行稳定的基础上,绚丽的UI和人性化的操作设计会给用户带来舒适的体验效果。前文我们学习了Blend设计简单的动画,可以使用StoryBoard快速创建一个动画效果,但是该动画效果看起来缺乏自然效果,让用户感觉太过机械化,大大的降低了用户体验性。为了是动画更为人性化,看起来更自然化,我们可以通过以下两个方式来解决:

     

    方法1. 使用前文所提及的,帧动画技术,为了是动画更自然化,可以在动画的关键细节中添加更多的帧,缩短每帧之间间隔效果,这样可以提高动画效果,但是,对于大型项目来说,这样的设计会耗费很多的精力设计,在项目完成后,项目维护相对复杂,一旦设计有所改动,需要全面修改其动画效果代码,所以,相对来说,该方法不太实用;

    方法2. 在Silverlight 3中,微软推出一个新的功能-Animation Easing,也称为缓冲动画。微软将11种常用的动画效果封装,开发人员和设计人员可以轻松调用,通过Animation Easing创建更自然化的动画效果。本文将详细介绍Animation Easing缓冲动画的入门知识,以及如何使用Blend设计Easing。

     

    理解Animation Easing(缓冲动画)

    在Silverlight中每个功能都会继承自不同的基类,实现不同的功能效果,Animation Easing(缓冲动画)也是一样,继承自EasingFunctionBase基类,在该类中,提供了一个属性EasingMode,通过该属性可以控件缓冲动画效果模式。Animation Easing(缓冲动画)效果模式被封装成一个枚举类型,分别是EaseIn,EaseOut,EaseInOut.Animation Easing(缓冲动画)的效果模式是一个重要的概念,该属性直接决定Animation Easing(缓冲动画)会在什么时候产生效果。这里我不想用过于官方的解释来说明这三种模式,根据我的使用体验,用自己的语言描述一下这三种动画模式的概念,

     

    EaseIn, 简单的可以理解为将该缓冲动画效果应用在动画实例开始,也就是一开始动画,马上执行该Animation Easing(缓冲动画)效果;

    EaseOut,简单的可以理解为将该缓冲动画效果应用在动画实例结束,也就是要结束动画前,马上执行该Animation Easing(缓冲动画)效果;

    EaseInOut,简单的可以理解为将动画的全过程平均分为两部分,该缓冲动画效果应用在第一部分,分别将EaseIn应用在第一部分的开始,EaseOut应用在第二部分的结束。例如,有个10秒的动画,被应用EaseInOut模式,Silverlight会将该动画平分为两个5秒的动画,将EaseIn应用在第一个5秒动画的开始,然后将EaseOut在第二个5秒动画结束前应用。

     

    对于三个效果模式的理解,我们将在后文实例中进行演示说明,这里仅需先对Animation Easing(缓冲动画)有个基础概念。作为软件设计人员和开发人员,应该都明白,所谓的动画效果,其实是计算机对于图形运行轨迹的计算不同,所产生的不同的视觉效果。而Animation Easing(缓冲动画)也是同理,在微软提供的11种Animation Easing(缓冲动画)动画中,运行了11个不同的方程式,从而产生11种动画效果。为了随后更好的理解这11种Animation Easing(缓冲动画)效果,首先需要了解一下最基础的方程式,通过方程式图形,可以大概明白动画运行效果。

    上图的t是表示时间,而f(t)表示动画目标对象属性,曲线表示其动画轨迹效果,不同的时间段,对象属性不同。

    看个例子说明,方程式图形效果,

    上图BackEase动画效果,是属性变化前,先向相反的方向变化,然后随着时间的增加,属性而增加。例如,一个按钮,宽度由小变大,应用该效果后,按钮会先变小,然后迅速宽度变大。而上图f(t)则表示按钮的宽度,t表示时间,蓝色的曲线表示按钮宽度的变化过程,

    根据以上的原理,我们来逐一学习一下微软提供的11种Animation Easing(缓冲动画)。在调用前需要了解以下几点:

    1. 要调用默认的11种Animation Easing(缓冲动画)首先需要引用System.Windows.Media.Animation命名空间;

    2. 由于这11中Animation Easing(缓冲动画)都是继承自同一个基类EasingFunctionBase,所以,都有EasingMode属性,也就是说都可以应用于EaseIn,EaseOut和EaseInOut;

    3. Animation Easing(缓冲动画)是运用在帧动画基础上,在使用前,需要调用动画对象的EasingFunction属性。由于EasingFunction属性每次只能被一个Animation Easing(缓冲动画)调用,所以,不能将多个Animation Easing(缓冲动画)效果添加到同一个动画对象中,这点较重要,需要谨记。

    对于11种Animation Easing(缓冲动画)效果,好友蝈蝈俊曾经详细介绍过,个人认为解释的恰到好处,容易理解,这里,我直接引用过来,另外,我补充了部分Easing动画的属性说明。(蝈蝈俊的Easing介绍原文)。

     

    • 倒退缓冲(BackEase):让动画在继续之前往后退一点。这有点象在斜坡上启动汽车,会往后倒退一点然后才前进。在BackEase中,有一个"Amplitude"属性,该属性可以简单理解为扩展宽度,也就是说动画继续之前往后退的宽度,默认设置为1,随着值的增加,倒退宽度也就越大。
    • 弹跳缓冲(BounceEase):有弹回效果的动画,类似我们前面提到的篮球落下,弹起,再落下,即弹跳反冲。该效果中包含两个属性,"Bounces"是表示弹跳几次,"Bounciness"是表示弹跳的速度,越大会越慢。
    • 圆缓冲(CircleEase):创建使用循环函数加速和/或减速的动画。 基于三角函数(圆函数)来加速动画,一开始的加速度比较慢,越往后加速度越快。
    • 立方体缓冲(CubicEase):创建使用公式加速和/或减速的动画。 与圆缓冲类似,但是是基于立方体函数的时间来产生一个一开始加速度较慢然后越来越快的动画。
    • 伸缩缓冲(ElasticEase):创建表示弹簧在停止前来回振荡的动画。类似于弹跳缓冲(BounceEase),它会让一个值摆动直到停下为止。该效果包含两个属性,"Oscillations"表示伸缩的次数,"Springiness"表示伸缩的速度.
    • 指数缓冲(ExponentialEase):创建使用指数公式加速和/或减速的动画。类似于圆缓冲和立方体缓冲,只是加速度的值是按照指数来变化的。该效果包含属性"Exponent",代表指数,越大效果越慢。
    • 乘方缓冲(PowerEase):创建使用公式  (其中,p 等于 PowerEase.Power  属性)加速和/或减速的动画。这是一种指数缓冲,缓冲的值与时间的乘方成比例。该效果有一个"Power"属性,表示时间t的指数,如果Power=2,则和平方缓冲动画相同效果;Power=3则和立方体缓冲动画效果相同,依次类推.
    • 平方缓冲(QuadraticEase):创建使用公式  加速和/或减速的动画。非常类似于CubicEase,除了在这个缓冲中,值是基于时间的平方。
    • 四次方缓冲(QuarticEase):创建使用公式  加速和/或减速的动画。类似于Cubic和Quadratic,只是值是基于时间的立方。
    • 五次方缓冲(QuinticEase):创建使用公式  加速和/或减速的动画。类似于Cubic、Quadratic和Quartic,值基于时间的五次方。
    • 正弦缓冲(SineEase):创建使用正弦公式加速和/或减速的动画。沿着正弦波来对值进行加速。

       

      上文主要是对Animation Easing(缓冲动画)进行概念性的描述,下文,将通过实例演示Animation Easing(缓冲动画)在Silverlight中的应用。

      对于Animation Easing(缓冲动画)的设计,Blend提供了方便的调用方法,首先打开上文提供的演示项目StoryBoardDemo.

      在该项目中,我们使用了多个关键帧描述图片运行轨迹。由于Animation Easing(缓冲动画)效果是基于帧动画的,所以,如果要使用Animation Easing(缓冲动画),只还需要在动画对象的帧上添加Animation Easing(缓冲动画)。

      为了让演示,简单明了,这里我删除了过去创建的5个关键帧中的4个,仅留下0:00:00的关键帧。

      在Object and Timeline中,更改时间为2

      在主设计窗口,拖动图片控件,Blend将自动创建帧动画,从0:00到0:02,

       

      在Object and Timeline中展开image控件,选中“RenderTransform”

       

      在右边的Properties属性栏,可以看到Easing的相关属性,

       

      EasingFunction下拉菜单,可以看到系统内置的11种Easing动画效果,

      在上文已经将各个动画效果和属性进行了描述,作为演示,这里我们随意选中一个,

      选中后,到Object and Timeline中试着运行查看效果,就可以看到Back In已经被应用到Image对象实例中。

       

      使用Blend应用内置缓冲动画到对象操作起来很简单,但是,在实际项目中,仅11种缓冲动画远不能满足实际需要,Blend还提供了通过KeySpline自定义Easing缓冲动画的功能。KeySpline仅支持关键帧动画。

      首先,在Objects and Timeline中,选中Image对象“RenderTransform”,在右边Properties属性栏,则可以看到Easing,选中“KeySpline”

       

      点击"Click here to deselect keyframes at time 0",即可看到自定义Easing动画窗口,

      鼠标点击黄色的节点,进行拖动,即可生成新的Easing缓动效果,

      回到Objects and Timeline再次运行动画,即可看到自定义KeySpline所生成的动画效果。

       

      通过本文的学习,对Animation Easing(缓冲动画)的应用应该有了一定的了解,如果能够熟练运用Easing在实际项目中,对用户的体验性会有很大的提高。

    转载于:https://www.cnblogs.com/xiaowie/p/9279746.html

    展开全文
  • 计算机动画是指用程序或工具生成一系列的静态画面,然后通过画面的连续播放来反映对象的运动变化过程.近年来,由于科学技术的不断进步,计算机动画技术已成为综合运用计算机图形学、物理学、机械学、心理学、美学、生命...
  • 动作、特效和动画

    2021-07-23 15:09:19
    动作、特效和动画动作包括基本动作和基本动作的组合,这些动作有缩放、移动、旋转等,而这些动作变化的速度也可以设定。 动作类是Action,类图如下: Action有3个子类,FiniteTimeAction 是一种受时间限制的...
  • Cocos2d-JS 动作、特效和动画

    千次阅读 2016-04-14 10:23:04
    动作包括基本动画和基本动作的组合,基本动作有缩放、移动、旋转等动作动作类是cc.Action。它的类图如图7-1所示。 从图中可以看出cc.Action的一个子类是cc.FiniteTimeAction,cc.FiniteTimeAction是一种...
  • 这是一个动画,展示了它的动作。 请参阅下面的说明。 动机 您是否发现自己正在查看具有长函数或深层嵌套的循环和条件的代码? 您是否曾经失去位置并开始滚动缓冲区以查看您的位置? 该插件旨在始终向您显示当前活动...
  • 动作动画的使用

    2017-09-02 11:28:57
    1、FadeIn和FadeOut 淡入淡出 ...①// 创建一个FadeIn动作,执行该动作的节点会在5秒内淡入 auto fadeIn = FadeIn::create(5); // 反转FadeIn动作,即节点会在5秒内淡出 auto fadeInReverse = fadeIn-
  • CCEase动作缓冲的解析

    千次阅读 2013-03-24 18:13:14
    在很多游戏引擎中,都有各种各样的动作,以及各色各样的动作缓冲,以便达到不同的效果。 在cocos2d中,同样也有这样一大批动作缓冲类。 先让我们分析下动作是如何运行的吧。 1、动作的要素 一般的动作至少有2个...
  • 利用双缓冲技术来显示动画

    千次阅读 2012-07-18 09:22:24
    现在,你已经能够对主表面的内容做直接修改了(就是锁住主表面然后绘制像素),也就是通过...答:一帧就是一副静止的画面,连续的帧就形成动画,如电视图象等。  我们通常说帧数,简单地说,就是在1秒钟时间里传输的
  • 骨骼动画详解-Spine

    2020-09-22 14:33:13
    游戏中人物的走动,跑动,攻击等动作是必不可少,实现它们的方法一般采用帧动画或者骨骼动画。 帧动画与骨骼动画的区别在于:帧动画的每一帧都是角色特定姿势的一个快照,动画的流畅性和平滑效果都取决于帧数的多少...
  • 网格顶点动画(变形动画)是针对于物体的形状可以随意变换并记录为关键帧的动画,虽然模型的顶点数据还是应该交给GPU绘制才是正道,CPU刷新模型顶点始终是个吃力不讨好的事(不过我好像至始至终就是在干吃力不讨好的...
  • 动作类(Action) 动作类(Action)是所有动作的基类,它创建的一个对象代表一个动作动作作用于Node,因此每个动作都需要由Node对象执行。动作类(Action)作为基类,实际上是一个接口,动作类的大多数实现类都派生于...
  • ->Run:进入奔跑,当时出冲刺或者奔跑行为会先进入这个状态进行缓冲,并不会有任何输出 Walk->Run:如果之前处于步行,则从步行切换到奔跑,并播放小幅度的过渡姿势(动画混合) Run Start:直接从静止切换到奔跑,...
  • 现在网上虽然讲解Unity3D动画的文章不少,但是却少很少带实际例子的。刚好我之前给美术做了个简单的例子,所以整理一下就共享给大家了。主要是做了两种动画,分别有例子,按空格可以改变动画。具体的制作过程不会...
  • Babylon.js 深入 - 第 1 章 - 动画(5) Babylon.js是一款基于WebGL的3D图形引擎,也是目前处于该领域世界领先水平的引擎之一。 动画可以让您的游戏或应用程序栩栩如生。在 `Babylon.js` 中制作动画有两种主要方式。您...
  • 目录12、多Slot上传顶点数据12.1、多Slot上传数据基本原理12.2、Assimp中间数据的简单转换12.2、Layout的定义12.3、缓冲区准备12.4、多Slot渲染13、动画动作状态机14、后记 12、多Slot上传顶点数据   在网格数据...
  • 目录3、Assimp的导入标志4、网格(Mesh)5、骨骼动画基础 3、Assimp的导入标志   一般的模型文件中,大多数情况下在建模时默认都保存成了OpenGL的右手坐标系,即z轴坐标垂直屏幕向外。而在D3D中习惯是左手坐标系,...
  • 在移动端h5游戏开发中,经常会遇到动画和动效的展现需求,比较常用的实现方法有css3、svg、定时器等,针对不同的场景和需求使用不同的技术,可以提升设计和开发的效率,保证产品的效果和质量,也能让用户有更好的...
  • 计算机制作动画的基本原理及运动规律动画的基本原理以及规律 第一节视觉原理 第二节制作原理 第三节动画运动的时间和节奏 第四节卡通角色的...角色的连续性动作是由原画师画出其中关键性的动态画面后,再由动画来...
  • 项目中经常用到物体移动,旋转,控制等已经自己来代码实现,代码制作动画也可以使用Dotween来实现。 Dotween提供了很多方法可以使用: using UnityEngine; using System.Collections; using DG.Tweening; ...
  • 比如有个格挡的动作 Block_End 和 Block_Start 这两个动作是,格挡开始和格挡结束,两个动作就是反向播放而已 进入 动画摄影表,而不是时间线, 选中所有骨骼动画,选中所有轨道里的关键帧,然后看一下一共是多少帧...
  • 动画的解释: 动画被用于属性的改变。 一个动画定义了属性值改变的曲线, 将一个属性值变化从一个值过渡到另一个值。 动画是由一连串的目标属性活动定义的, 平缓的曲线算法能够引发一个定义时间内属性的持续变化。 ...
  • cocosCreator 骨骼动画

    2020-07-04 21:47:14
    //目标缓冲 this._target = gl.TEXTURE_2D; //首先会在内部创建glID这个是纹理在GPU中的标识 this._glID = gl.createTexture(); // always alloc texture in GPU when we create it. //创建时总是在gpu中分配纹理 ...
  • 几款动画效果的Flash菜单及mxp组件,全部都响应鼠标动作,鼠标动画,动态的Flash菜单,鼠标在菜单上滑动,菜单背景会有所变化,有的还有动画缓冲效果。
  • 模型的骨骼动画技术讲解

    千次阅读 2017-03-23 20:15:41
    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN...CSDN视频网址:http://edu.csdn.net/lecturer/144 骨骼动画实际上是两部分的过程。第一个由美术执行,第二个由程序员(或者你写的引擎)执行。第一部分发生

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,358
精华内容 2,943
关键字:

动画缓冲动作

友情链接: uCOS-II_20091031.rar