Home Manual Reference Source Repository

src/axis/grid-axis-generator.js

/**
 * A generator to create data for grid axis according to a `bpm` and a `meter`.
 *
 * [example usage](./examples/layer-axis.html)
 *
 * @param {Number} bpm - The number of beats per minutes.
 * @param {String} signature - The meter of the mesure (`'4/4'`, `'3/8'`, ...).
 * @return {Function} - The configured function returning the data when called.
 */
export default function gridAxisGenerator(bpm, signature) {
  const _bps =  bpm / 60; // sec
  const _unit = 1 / parseInt(signature.split('/')[1], 10);
  const _nbrUnitsPerMesure = parseInt(signature.split('/')[0], 10);

  return function(timeContext) {
    const duration = timeContext.visibleDuration;
    const offset = timeContext.offset;
    const data = [];

    // const min = Math.min(-offset, 0);
    const min = - offset;
    // remove the timeline's offset to keep the layer centered
    const max = duration - offset;

    // define pixels for 1 second
    const pixelsPerSecond = timeContext.computedPixelsPerSecond;
    // time for one _unit
    const unitTime = 1 / _bps;
    // define the first tick > min
    const modulo = min % unitTime;
    const mult = (min - modulo) / unitTime;
    const firstTickTime = unitTime * mult;
    // track which position of current beat in the mesure
    let positionInMesure = mult % _nbrUnitsPerMesure;

    // remove not focused beats, if zoomed out
    const pixelsPerTick = pixelsPerSecond / _bps;
    const minStep = 5;

    // time should be
    for (let time = firstTickTime; time < max; time += unitTime) {
      // find first beat
      const focused = (positionInMesure++ % _nbrUnitsPerMesure === 0);
      // ignore if pixels per ticks is too small
      if ((pixelsPerTick <= minStep) && !focused) { continue; }

      data.push({ time, focused });
    }

    return data;
  };
}