具体的计时器功能JavaScript

时间:2017-04-03 12:45:49

标签: javascript

我是新来的,马上直接蝙蝠。 我刚刚开始学习编程,想出了这样的功能(函数?)。我知道我想从她那里得到什么,但我不知道如何写它,但我不知道这些条款。任何人都可以帮助我吗?

set timer (10000ms);
autostart timer = true/false;
control_element = any html element (button/div) toggle play/pause timer;

if timer < 9001ms && timer >= 8000ms {
    if control_element == play {
        do function1;
    }
    else if control_element == pause {
        cancel function1;
    }
}
else if timer < 8000ms && timer >= 7000ms {
    if control_element == play {
        do function2;
    }
    else if control_element == pause {
        cancel function2;
    }
}
else if timer < 7000ms && timer > 0ms {
    if control_element == play {
        do function3;
    }
    else if control_element == pause {
        cancel function3;
    }
}
else if timer == 0ms {
    set timer = 10000ms;
    set timer = pause;
}

我找到了一个能够播放和暂停的优秀计时器,但我不知道如何根据我的需要配置它:javascript countdown timer pause resume

1 个答案:

答案 0 :(得分:0)

使用1毫秒的间隔,只需注册您的任务。我在下面列出了一个计时器类的例子:

&#13;
&#13;
/**
 * This is a Timer class that can measure time in milliseconds
 * @class Timer
 */
var Timer = (function() {
  /**
   * Creates an instance of Timer.
   * Max is how many milliseconds the "Timer" should live
   * Rate is how often the timer should test if any tasks is ready to fire
   * (A lower rate gives a more precise timer, but costs more calculation power to run)
   *
   * @param {any} [max=Infinity]
   * @param {number} [rate=0]
   * @returns {Timer}
   *
   * @memberOf Timer
   */
  function Timer(max, rate) {
    if (max === void 0) {
      max = Infinity;
    }
    if (rate === void 0) {
      rate = 0;
    }
    this.max = max;
    this.rate = rate;
    this.interval = setInterval(this.tick.bind(this), this.rate);
    /**
     * Current state of "Timer"
     *
     * @private
     * @type {boolean}
     * @memberOf Timer
     */
    this.run = false;
    /**
     * A list of registered Tasks
     *
     * @type { {time: number, cb: () => any}[] }
     * @memberOf Timer
     */
    this.tasks = [];
    /**
     * A list of changes that makes up the "timeline" of this "Timer"
     * "state" determines if the clock is "running"
     * "date" determines when the "Timer" changed to this state
     *
     * @private
     * @type {{ state: boolean, date: number }[]}
     * @memberOf Timer
     */
    this.timeline = [];
  }
  /**
   * Tick is the "belly of the beast"
   * tick is checked every
   *
   * @private
   * @returns
   *
   * @memberOf Timer
   */
  Timer.prototype.tick = function() {
    //Dont calculate anything if the "Timer" isn't ticking
    if (!this.run) {
      return;
    }
    //Get current time
    var currentMilliseconds = this.getCurrentMilliseconds();
    //Loop though tasks
    for (var taskIndex = 0; taskIndex < this.tasks.length; taskIndex++) {
      var task = this.tasks[taskIndex];
      //If task is to be fired
      if (task.time <= currentMilliseconds) {
        //Call task callback
        task.cb();
        //Remove task
        this.tasks.splice(taskIndex, 1);
        //Displace "taskIndex" to accomodate list length change
        taskIndex -= 1;
      }
    }
    //Terminate if "Timer" has run out of ticks
    if (currentMilliseconds > this.max) {
      this.terminate;
    }
  };
  /**
   * Destroys the "Timer" so it can't be started again, but leaves data like unresolves tasks
   *
   * @returns {Timer}
   *
   * @memberOf Timer
   */
  Timer.prototype.terminate = function() {
    clearInterval(this.interval);
    return this;
  };
  /**
   * Register a task to run when the "Timer" passed "time" milliseconds
   * When the "Timer" passes "time" milliseconds, the "Timer" will active the supplied "cb" function and remove the task
   *
   * @param {() => any} cb
   * @param {number} [time=0]
   * @returns {Timer}
   *
   * @memberOf Timer
   */
  Timer.prototype.addTask = function(cb, time) {
    if (time === void 0) {
      time = 0;
    }
    this.tasks.push({
      cb: cb,
      time: time
    });
    return this;
  };
  /**
   * Run through the timeline and calculate milliseconds time spent in "running" state
   *
   * @returns {number}
   *
   * @memberOf Timer
   */
  Timer.prototype.getCurrentMilliseconds = function() {
    //Variable to hold calculated milliseconds
    var currentMilliseconds = 0;
    //If no timeline yet, return immidiately
    if (this.timeline.length < 1) {
      return currentMilliseconds;
    }
    //Run through the timeline and add time spent in "running" state to "current"
    for (var timelineIndex = 1; timelineIndex < this.timeline.length; timelineIndex++) {
      var timelineA = this.timeline[timelineIndex - 1];
      var timelineB = this.timeline[timelineIndex];
      if (!timelineB.state) {
        currentMilliseconds += timelineB.date - timelineA.date;
      }
    }
    //If we are currently in a "running" state, add time from now to start of that state into "current"
    if (this.timeline[this.timeline.length - 1].state === true) {
      currentMilliseconds += Date.now() - this.timeline[this.timeline.length - 1].date;
    }
    //return calculated milliseconds
    return currentMilliseconds;
  };
  /**
   * Starts or stops the Timer
   * If no specific state (true/false) is set the state is set to the inverse of the current "this.run"
   *
   * @param {boolean} [state=!this.run]
   * @returns {Timer}
   *
   * @memberOf Timer
   */
  Timer.prototype.startStop = function(state) {
    if (state === void 0) {
      state = !this.run;
    }
    //Check if we are already in this state
    //If we are, return Timer for chaining and terminate (stopping a stopped watch is redundant)
    if ((this.timeline.length > 0 ? this.timeline[this.timeline.length - 1].state === state : !state)) {
      return this;
    }
    //Add statechange to timeline (see the "timeline" property and "getCurrentTick" method)
    this.timeline.push({
      state: state,
      date: Date.now()
    });
    //Set running state
    this.run = state;
    //Return Timer for chaining
    return this;
  };
  return Timer;
}());

//Testing
//Create a timer that lives for 10 seconds and checks tasks every 100 milliseconds
var timer = new Timer(10 * 1000, 100);

//Begin "chaining"
timer
  //Add task to fire after 500 milliseconds
  //This will be the third task to fire
  .addTask(function() {
    console.log("function 1");
  }, 500)
  //Add task to fire after 300 milliseconds
  //This will be the second task to fire
  .addTask(function() {
    console.log("function 2");
  }, 300)
  //Add task to fire after 500 milliseconds
  //This will be the fourth task to fire
  .addTask(function() {
    console.log("function 3");
  }, 500)
  //Add task to fire after 100 milliseconds
  //This will be the first task to fire
  .addTask(function() {
    console.log("function 4");
  }, 100)
  //Start the Timer
  .startStop();

//After 1.5 second, pause timer
setTimeout(function() {
  timer.startStop(false);
}, 1500);
//After 2.5 second, start timer (which will be paused from above command)
setTimeout(function() {
  timer.startStop(true);
}, 2500);

//Same as above without specified state
setTimeout(function() {
  timer.startStop();
}, 4500);
//Same as above without specified state
setTimeout(function() {
  timer.startStop();
}, 7500);
&#13;
&#13;
&#13;

<强>更新

使用Date对象添加了更好的精度。