控制物体运动自定义JavaScript函数(匀速、变速)

1.改变某一个元素一段横向距离。匀速动画,可以匀速控制某一元素element移动到目标位置target 上;

 //匀速动画
    function animate(element, target) {
      //清理定时器
      clearInterval(element.timeId);
      element.timeId = setInterval(function () {
        //获取元素的当前位置
        var current = element.offsetLeft;
        //移动的步数
        var step = 10;
        step = target > current ? step : -step;
        current += step;
        if (Math.abs(current - target) > Math.abs(step)) {
          element.style.left = current + "px";
        } else {
          clearInterval(element.timeId);
          element.style.left = target + "px";
        }
      }, 20);
    }

 1.改变某一个元素一段横向距离。变速动画,可以变速(由快到慢)控制某一元素element移动到目标位置target 上;

变速原理 target-current/10;计算结果可能会产生小数,会出问题;所以这样解决,当步数为正数时向上取整Math.ceil(),当步数为负数时向下取整Math.floor()

//变速动画
    function animate(element, target) {
      //清理定时器
      clearInterval(element.timeId);
      element.timeId = setInterval(function () {
        //获取元素的当前位置
        var current = element.offsetLeft;
        //移动的步数
        var step = (target-current)/10;
        step = step>0?Math.ceil(step):Math.floor(step);
        current += step;
        element.style.left = current + "px";
        if(current==target) {
          //清理定时器
          clearInterval(element.timeId);
        }
        //测试代码:
        console.log("目标位置:"+target+",当前位置:"+current+",每次移动步数:"+step);
      }, 20);
    }

3.获取任意对象,改变其对象的某一属性的值

//获取任意一个元素的任意一个属性的当前的值---当前属性的位置值
  function getStyle(element,attr) {
    return window.getComputedStyle? window.getComputedStyle(element,null)[attr]:element.currentStyle[attr]||0;
  }



  //element---元素
  //json---对象---多个属性及多个目标值
  //fn---函数
  function animate(element,json,fn) {
    clearInterval(element.timeId);
    element.timeId=setInterval(function () {
      var flag=true;//默认,假设,全部到达目标
      for(var attr in json){
        //获取元素这个属性的当前的值
        var current=parseInt(getStyle(element,attr));
        //当前的属性对应的目标值
        var target=json[attr];
        //移动的步数
        var step=(target-current)/10;
        step=step>0?Math.ceil(step):Math.floor(step);
        current+=step;//移动后的值
        element.style[attr]=current+"px";
        if(current!=target){
          flag=false;
        }
      }
      if(flag){
        //清理定时器
        clearInterval(element.timeId);
        //所有的属性到达目标才能使用这个函数,前提是用户传入了这个函数
        if(fn){
          fn();
        }
      }


      //测试代码
      console.log("目标:"+target+",当前:"+current+",每次的移动步数:"+step);
    },20);
  }

4.获取任意对象,改变其对象的多一属性的值 

 //获取任意的一个属性的当前的属性值: left--->此时的left属性的值,width---当前的元素的宽
    function getStyle(element,attr) {
      //判断浏览器是否支持这个方法
      return window.getComputedStyle? window.getComputedStyle(element,null)[attr]:element.currentStyle[attr];
    }
    //匀速动画

    //element---元素
    //attr---属性名字
    //target---目标位置
    function animate(element,attr ,target) {
      //清理定时器
      clearInterval(element.timeId);
      element.timeId = setInterval(function () {
        //获取元素的当前位置
        var current = parseInt(getStyle(element,attr));//数字类型//===============================
        //移动的步数
        var step = (target-current)/10;
        step = step>0?Math.ceil(step):Math.floor(step);
        current += step;
        element.style[attr] = current + "px";//============================================
        if(current==target) {
          //清理定时器
          clearInterval(element.timeId);
        }
        //测试代码:
        console.log("目标位置:"+target+",当前位置:"+current+",每次移动步数:"+step);
      }, 20);
    }

5.获取任意对象,改变其对象的多一属性的值 ,并可回调函数,也就是可以传入函数作为参数

//获取任意一个元素的任意一个属性的当前的值---当前属性的位置值
  function getStyle(element,attr) {
    return window.getComputedStyle? window.getComputedStyle(element,null)[attr]:element.currentStyle[attr]||0;
  }

  //element---元素
  //json---对象---多个属性及多个目标值
  //fn---函数
  function animate(element,json,fn) {
    clearInterval(element.timeId);
    element.timeId=setInterval(function () {
      var flag=true;//默认,假设,全部到达目标
      for(var attr in json){
        //获取元素这个属性的当前的值
        var current=parseInt(getStyle(element,attr));
        //当前的属性对应的目标值
        var target=json[attr];
        //移动的步数
        var step=(target-current)/10;
        step=step>0?Math.ceil(step):Math.floor(step);
        current+=step;//移动后的值
        element.style[attr]=current+"px";
        if(current!=target){
          flag=false;
        }
      }
      if(flag){
        //清理定时器
        clearInterval(element.timeId);
        //所有的属性到达目标才能使用这个函数,前提是用户传入了这个函数
        if(fn){
          fn();
        }
      }


      //测试代码
      console.log("目标:"+target+",当前:"+current+",每次的移动步数:"+step);
    },20);
  }

//调用。按钮button,id为bth。自行写html

  my$("btn1").onclick=function () {

    var json1={"width":400,"height":500,"left":500,"top":80};
      animate(my$("dv"),json1,function () {
        var json2={"width":40,"height":50,"left":50,"top":800};
        animate(my$("dv"),json2,function () {
          var json3={"width":450,"height":550,"left":550,"top":600};
          animate(my$("dv"),json3);
        });
      });
  };

6.终极版,还可以改变透明度和层级

  //获取任意一个元素的任意一个属性的当前的值---当前属性的位置值
  function getStyle(element, attr) {
    return window.getComputedStyle ? window.getComputedStyle(element, null)[attr] : element.currentStyle[attr] || 0;
  }

  function animate(element, json, fn) {
    clearInterval(element.timeId);//清理定时器
    //定时器,返回的是定时器的id
    element.timeId = setInterval(function () {
      var flag = true;//默认,假设,全部到达目标
      //遍历json对象中的每个属性还有属性对应的目标值
      for (var attr in json) {
        //判断这个属性attr中是不是opacity
        if (attr == "opacity") {
          //获取元素的当前的透明度,当前的透明度放大100倍
          var current = getStyle(element, attr) * 100;
          //目标的透明度放大100倍
          var target = json[attr] * 100;
          var step = (target - current) / 10;
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
          current += step;//移动后的值
          element.style[attr] = current / 100;
        } else if (attr == "zIndex") { //判断这个属性attr中是不是zIndex
          //层级改变就是直接改变这个属性的值
          element.style[attr] = json[attr];
        } else {
          //普通的属性
          //获取元素这个属性的当前的值
          var current = parseInt(getStyle(element, attr));
          //当前的属性对应的目标值
          var target = json[attr];
          //移动的步数
          var step = (target - current) / 10;
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
          current += step;//移动后的值
          element.style[attr] = current + "px";
        }
        //是否到达目标
        if (current != target) {
          flag = false;
        }
      }
      if (flag) {
        //清理定时器
        clearInterval(element.timeId);
        //所有的属性到达目标才能使用这个函数,前提是用户传入了这个函数
        if (fn) {
          fn();
        }
      }
      //测试代码
      console.log("目标:" + target + ",当前:" + current + ",每次的移动步数:" + step);
    }, 20);
  }


  //zIndex:1000
  //透明度: 数字类型----小数---放大100倍
  my$("btn1").onclick = function () {

    var json1 = {"width": 400, "height": 500, "left": 500, "top": 80, "opacity": 0.2};
    animate(my$("dv"), json1, function () {
      animate(my$("dv"), {"width": 40, "height": 50, "left": 0, "top": 0, "opacity": 1, "zIndex": 1000});
    });
  };

 

<think>嗯,用户这次的提问是关于"帧节奏控制"的具体实现方法和概念解析。从查询内容看,用户应该是个开发者或动画设计人员,可能正在实现一个需要精细控制动画节奏的项目,比如游戏角色动画或UI交互效果。回顾对话历史,用户之前询问过工作节奏控制的问题,但这次明显转向技术领域。我注意到用户特别强调要"实现方法或示例",说明ta需要实操性内容而非纯理论。有趣的是,用户引用的素材里有三个相关概念:设计师自由度、时间刻度控制和浏览器兼容性,这暗示ta的关注点可能在web前端动画实现。用户的问题可以拆解成三个层次:首先是基础概念(什么是帧节奏控制),然后是核心技术(如何实现),最后是应用示例。特别要注意引用[3]提到的timingfunction概念,这是实现帧节奏的关键技术点。在技术实现部分,应该覆盖全链路:从理论概念(时间函数)到具体API(如requestAnimationFrame),再到性能优化(避免卡顿)。考虑到用户提到"设计师更自由发挥",还要强调美术资源如何与代码配合,比如雪碧图序列的处理。最后给出的示例代码需要兼顾技术准确性和教学价值。选择用JavaScript实现是因为引用[2]提到浏览器兼容性要求,而纯CSS方案限制较多。在例子中特意加入变速控制(speed参数)和时间函数(easeOutCubic)正是回应用户引用的核心要素。关于节奏变化的重要性,引用[4]的足球案例其实非常贴切——动画节奏和体育节奏同理。虽然最后没在回复中保留这个比喻,但这个思路提醒我强调"节奏变化比匀速更重要"的设计原则。</think> 以下关于帧节奏控制的解析基于动画原理与前端实现技术,结合引用内容的结构化整理: ### 一、帧节奏控制的核心概念 1. **定义本质** 通过精确控制**每一帧的播放时长**($t_{frame}$)和**帧序列切换规则**,实现对动画速度、流畅度及交互响应的编程控制(引用[3]的核心原理延伸)。 2. **核心要素** - **帧率(FPS)**:每秒渲染的帧数,计算公式: $$ FPS = \frac{1}{t_{frame}} $$ - **时间函数(Timing Function)**:定义动画进度的变化规律(如匀速/缓动) ```javascript // CSS示例:贝塞尔曲线控制加速度 .element { transition: transform 1s cubic-bezier(0.68, -0.55, 0.27, 1.55); } ``` ### 二、关键技术实现方案 #### ▶ 基础方法:时间轴驱动 ```javascript // 纯JS实现帧序列控制 let frameIndex = 0; const frameDuration = 1000 / 24; // 按24FPS计算每帧时长 const animate = () => { if (frameIndex >= totalFrames) return; drawFrame(frames[frameIndex]); // 绘制当前帧 frameIndex++; // 通过setInterval控制节奏(引用[2]核心原理) setTimeout(animate, frameDuration); }; ``` #### ▶ 现代API:高精度控制 ```javascript // 使用requestAnimationFrame实现精准帧同步 let lastTime = 0; const animate = (timestamp) => { if (!lastTime) lastTime = timestamp; const elapsed = timestamp - lastTime; if (elapsed > frameDuration) { frameIndex = (frameIndex + 1) % totalFrames; drawFrame(frames[frameIndex]); lastTime = timestamp; } requestAnimationFrame(animate); // 浏览器自动匹配刷新率 }; ``` #### ▶ 交互式控制实现(引用[2]需求) ```javascript // 可暂停/变速控制器 class FramePlayer { constructor(frames) { this.frames = frames; this.speed = 1; // 1=正常速度 this.isPlaying = false; } play() { this.isPlaying = true; this._animate(); } _animate() { if (!this.isPlaying) return; // 根据speed动态计算帧间隔 const interval = 1000 / (24 * this.speed); // ...渲染逻辑 this._raf = requestAnimationFrame(() => this._animate()); } setSpeed(speed) { this.speed = speed; // 实现变速(引用[3]动态节奏) } stop() { cancelAnimationFrame(this._raf); this.isPlaying = false; } } ``` ### 三、典型应用场景分析 1. **游戏角色动画** - 需求:行走(8帧/循环)、攻击(12帧/循环)独立控制 - 方案:多动画轨道 + 差异化帧间隔配置 2. **数据可视化进度条** - 需求:加载进度从0%-100%带缓冲效果 - 实现:使用`ease-out`时间函数(引用[3]的慢进快出效果) $$ progress(t) = 1 - (1 - t)^3 \quad (t \in [0,1]) $$ 3. **UI交互动效** - 案例:按钮点击波纹扩散(通过逐帧缩放透明度实现) ### 四、性能优化要点 1. **帧预测技术** 动态跳帧策略:当计算延迟时自动跳过中间帧,保持整体节奏稳定 ```javascript if (elapsed > 2 * frameDuration) { frameIndex += Math.floor(elapsed / frameDuration); // 跳帧补偿 } ``` 2. **资源预加载** 首帧优先加载机制(引用[2]"素材准备"的工程化实践) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值