我正在使用Simple Timer jQuery插件,并且有两个问题:
我不需要计时器中的新行。如何在“ 00:00:00”这样的一行上显示它,而不是下图中的结果?
如何使计时器结束后计时器以红色闪烁?
这是我的代码:
<script src="./jquery.js"></script>
<script src="./jquery.simple.timer.js"></script>
<div class="timer-1" data-seconds-left="20"></div>
<script>
$(function(){
$('.timer-1').startTimer({
onComplete: function(element){
element.addClass('is-complete');
},
});
});
</script>
结果如下:
答案 0 :(得分:0)
要将所有时间元素保持在同一行,可以float
。
要在完成后使计时器闪烁,可以使用CSS animations。
这是一个示范:
$('.timer-1').startTimer({
onComplete: function(element) {
element.addClass('is-complete');
},
});
.timer-1 {
font-size: 2em;
}
.jst-hours,
.jst-minutes,
.jst-seconds {
float: left;
}
.is-complete {
color: red;
-webkit-animation-name: blinker;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: cubic-bezier(1.0, 0, 0, 1.0);
-webkit-animation-duration: .7s;
}
@-webkit-keyframes blinker {
from {
opacity: 1.0;
}
to {
opacity: 0.0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-simple-timer@1.0.1/jquery.simple.timer.js"></script>
<div class="timer-1" data-seconds-left="3"></div>
TL; DR:无需浮动。
Examples表明elementContainer
选项将生成内联元素(如<span>
),而不是块元素(如默认的<div>
),因此无需{ {1}}个他们:
float
version I was using on jsDelivr不包含此功能,因此,由于缺少CDN,我在下面的示例中使用了更新的源代码。您从GitHub或author's site获得的版本中确实包含该版本。另外,请参见this commit贡献的Alex Sandro。
$('.timer-1').startTimer({
elementContainer: "span"
});
// Polyfill new JS features for older browser
Number.isFinite = Number.isFinite || function(value) {
return typeof value === 'number' && isFinite(value);
}
var timer;
var Timer = function(targetElement) {
this._options = {};
this.targetElement = targetElement;
return this;
};
Timer.start = function(userOptions, targetElement) {
timer = new Timer(targetElement);
mergeOptions(timer, userOptions);
return timer.start(userOptions);
};
// Writes to `this._options` object so that other
// functions can access it without having to
// pass this object as argument multiple times.
function mergeOptions(timer, opts) {
opts = opts || {};
// Element that will be created for hours, minutes, and seconds.
timer._options.elementContainer = opts.elementContainer || 'div';
var classNames = opts.classNames || {};
timer._options.classNameSeconds = classNames.seconds || 'jst-seconds', timer._options.classNameMinutes = classNames.minutes || 'jst-minutes', timer._options.classNameHours = classNames.hours || 'jst-hours', timer._options.classNameClearDiv = classNames.clearDiv || 'jst-clearDiv', timer._options.classNameTimeout = classNames.timeout || 'jst-timeout';
}
Timer.prototype.start = function(options) {
var that = this;
var createSubElements = function(timerBoxElement) {
var seconds = document.createElement(that._options.elementContainer);
seconds.className = that._options.classNameSeconds;
var minutes = document.createElement(that._options.elementContainer);
minutes.className = that._options.classNameMinutes;
var hours = document.createElement(that._options.elementContainer);
hours.className = that._options.classNameHours;
var clearElement = document.createElement(that._options.elementContainer);
clearElement.className = that._options.classNameClearDiv;
return timerBoxElement.
append(hours).
append(minutes).
append(seconds).
append(clearElement);
};
this.targetElement.each(function(_index, timerBox) {
var that = this;
var timerBoxElement = $(timerBox);
var cssClassSnapshot = timerBoxElement.attr('class');
timerBoxElement.on('complete', function() {
clearInterval(timerBoxElement.intervalId);
});
timerBoxElement.on('complete', function() {
timerBoxElement.onComplete(timerBoxElement);
});
timerBoxElement.on('complete', function() {
timerBoxElement.addClass(that._options.classNameTimeout);
});
timerBoxElement.on('complete', function() {
if (options && options.loop === true) {
timer.resetTimer(timerBoxElement, options, cssClassSnapshot);
}
});
timerBoxElement.on('pause', function() {
clearInterval(timerBoxElement.intervalId);
timerBoxElement.paused = true;
});
timerBoxElement.on('resume', function() {
timerBoxElement.paused = false;
that.startCountdown(timerBoxElement, {
secondsLeft: timerBoxElement.data('timeLeft')
});
});
createSubElements(timerBoxElement);
return this.startCountdown(timerBoxElement, options);
}.bind(this));
};
/**
* Resets timer and add css class 'loop' to indicate the timer is in a loop.
* $timerBox {jQuery object} - The timer element
* options {object} - The options for the timer
* css - The original css of the element
*/
Timer.prototype.resetTimer = function($timerBox, options, css) {
var interval = 0;
if (options.loopInterval) {
interval = parseInt(options.loopInterval, 10) * 1000;
}
setTimeout(function() {
$timerBox.trigger('reset');
$timerBox.attr('class', css + ' loop');
timer.startCountdown($timerBox, options);
}, interval);
}
Timer.prototype.fetchSecondsLeft = function(element) {
var secondsLeft = element.data('seconds-left');
var minutesLeft = element.data('minutes-left');
if (Number.isFinite(secondsLeft)) {
return parseInt(secondsLeft, 10);
} else if (Number.isFinite(minutesLeft)) {
return parseFloat(minutesLeft) * 60;
} else {
throw 'Missing time data';
}
};
Timer.prototype.startCountdown = function(element, options) {
options = options || {};
var intervalId = null;
var defaultComplete = function() {
clearInterval(intervalId);
return this.clearTimer(element);
}.bind(this);
element.onComplete = options.onComplete || defaultComplete;
element.allowPause = options.allowPause || false;
if (element.allowPause) {
element.on('click', function() {
if (element.paused) {
element.trigger('resume');
} else {
element.trigger('pause');
}
});
}
var secondsLeft = options.secondsLeft || this.fetchSecondsLeft(element);
var refreshRate = options.refreshRate || 1000;
var endTime = secondsLeft + this.currentTime();
var timeLeft = endTime - this.currentTime();
this.setFinalValue(this.formatTimeLeft(timeLeft), element);
intervalId = setInterval((function() {
timeLeft = endTime - this.currentTime();
// When timer has been idle and only resumed past timeout,
// then we immediatelly complete the timer.
if (timeLeft < 0) {
timeLeft = 0;
}
element.data('timeLeft', timeLeft);
this.setFinalValue(this.formatTimeLeft(timeLeft), element);
}.bind(this)), refreshRate);
element.intervalId = intervalId;
};
Timer.prototype.clearTimer = function(element) {
element.find('.jst-seconds').text('00');
element.find('.jst-minutes').text('00:');
element.find('.jst-hours').text('00:');
};
Timer.prototype.currentTime = function() {
return Math.round((new Date()).getTime() / 1000);
};
Timer.prototype.formatTimeLeft = function(timeLeft) {
var lpad = function(n, width) {
width = width || 2;
n = n + '';
var padded = null;
if (n.length >= width) {
padded = n;
} else {
padded = Array(width - n.length + 1).join(0) + n;
}
return padded;
};
var hours = Math.floor(timeLeft / 3600);
timeLeft -= hours * 3600;
var minutes = Math.floor(timeLeft / 60);
timeLeft -= minutes * 60;
var seconds = parseInt(timeLeft % 60, 10);
if (+hours === 0 && +minutes === 0 && +seconds === 0) {
return [];
} else {
return [lpad(hours), lpad(minutes), lpad(seconds)];
}
};
Timer.prototype.setFinalValue = function(finalValues, element) {
if (finalValues.length === 0) {
this.clearTimer(element);
element.trigger('complete');
return false;
}
element.find('.' + this._options.classNameSeconds).text(finalValues.pop());
element.find('.' + this._options.classNameMinutes).text(finalValues.pop() + ':');
element.find('.' + this._options.classNameHours).text(finalValues.pop() + ':');
};
$.fn.startTimer = function(options) {
this.TimerObject = Timer;
Timer.start(options, this);
return this;
};
$('.timer-1').startTimer({
elementContainer: "span"
});