Clip = function (opts) {

    opts = opts || {};

    /**
     * @type {string}
     */
    this.name = opts.name || '';

    /**
     * @type {Object}
     */
    this.target = opts.target;

    /**
     * @type {number}
     */
    this.life = opts.life || 1000;

    /**
     * @type {number}
     */
    this.delay = opts.delay || 0;

    /**
     * @type {number}
     */
    this.gap = opts.gap || 0;

    /**
     * @type {number}
     */
    this.playbackRate = opts.playbackRate || 1;


    this._initialized = false;

    this._elapsedTime = 0;

    this._loop = opts.loop == null ? false : opts.loop;
    this.setLoop(this._loop);

    if (opts.easing != null) {
        this.setEasing(opts.easing);
    }

    /**
     * @type {Function}
     */
    this.onframe = opts.onframe || noop;

    /**
     * @type {Function}
     */
    this.onfinish = opts.onfinish || noop;

    /**
     * @type {Function}
     */
    this.onrestart = opts.onrestart || noop;

    this._paused = false;
}
@constructor
@alias clay.animation.Clip
@param {Object} [opts]
@param {Object} [opts.target]
@param {number} [opts.life]
@param {number} [opts.delay]
@param {number} [opts.gap]
@param {number} [opts.playbackRate]
@param {boolean|number} [opts.loop] If loop is a number, it indicate the loop count of animation
@param {string|Function} [opts.easing]
@param {Function} [opts.onframe]
@param {Function} [opts.onfinish]
@param {Function} [opts.onrestart]