制作自己的countUp.js插件需要以下步骤:
1. 插件的结构
首先我们需要构建插件的基本结构,可以选择通过函数或对象的方式来组织代码。然后需要定义countUp插件对象,其需要包括如下属性:
startVal
: 开始计数的值;endVal
: 结束计数的值;duration
: 计数持续时间;options
: 自定义选项,包括前缀、后缀、小数点位数等等。
2. 实现计数
然后需要实现计数的方法,我们可以选择借助requestAnimationFrame来实现单次更新计数器的值。在计数完成之后,需要删除该计数节点。
3. 添加到DOM
最后需要把计数器添加到DOM中。我们可以选择创建一个新的DOM元素并插入到指定节点中。同时,在某些情况下,我们还可以完善计数器的一些表现形式,比如添加动画效果等等。
示例1:以函数的方式实现countUp.js插件
下面给出一个以函数的方式实现的countUp插件:
function countUp(el, startVal, endVal, duration, options) {
var reqAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var startTime = null;
var endTime = duration;
var currentVal = startVal;
var elem = document.getElementById(el);
var decimalPlaces = isNaN(options.decimalPlaces = Math.abs(options.decimalPlaces)) ? 0 : options.decimalPlaces;
var prefix = options.prefix !== undefined ? options.prefix : '';
var suffix = options.suffix !== undefined ? options.suffix : '';
var countTo = function (timestamp) {
if (!startTime) startTime = timestamp;
var currentTime = timestamp - startTime;
var progress = currentTime / endTime;
progress = progress > 1 ? 1 : progress;
currentVal = startVal + (endVal - startVal) * countUpEasing(progress);
currentVal = parseFloat(currentVal.toFixed(decimalPlaces));
if (elem) elem.innerHTML = prefix + formatNumber(currentVal) + suffix;
if (progress < 1) reqAnimationFrame(countTo);
};
reqAnimationFrame(countTo);
}
function countUpEasing(t) {
return --t * t * t + 1;
}
function formatNumber(num) {
num = num.toFixed(2);
num = num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return num;
}
在这个代码段中,我们定义了一个countUp函数,它的参数分别是:
el
: DOM元素的id;startVal
: 开始计数的值;endVal
: 结束计数的值;duration
: 计数持续时间;options
: 自定义选项对象,包括前缀、后缀、小数点位数等等。
这个函数中主要工作是通过requestAnimationFrame方法来实现计数器的更新,并在计数结束之后删除计数节点。在更新计数器的时候,我们提供了一个countUpEasing函数来进行缓动运动。同时,我们还提供了一个格式化数字的函数formatNumber来添加千位分隔符并保留小数点位数。
示例2:以对象的方式实现countUp.js插件
下面给出一个以对象的方式实现的countUp插件:
function CountUp(options) {
var _this = this;
var reqAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var defaults = {
el: null,
startVal: 0,
endVal: 100,
duration: 1000,
prefix: '',
suffix: '',
decimalPlaces: 0,
easingFn: null,
onComplete: null
};
var options = _extend(defaults, options);
function _extend(objA, objB) {
for (var key in objB) {
if (objB.hasOwnProperty(key)) {
objA[key] = objB[key];
}
}
return objA;
}
_this.start = function () {
var startTime = null;
var endTime = options.duration;
var currentVal = options.startVal;
var elem = document.getElementById(options.el);
var decimalPlaces = isNaN(options.decimalPlaces = Math.abs(options.decimalPlaces)) ? 0 : options.decimalPlaces;
var prefix = options.prefix !== undefined ? options.prefix : '';
var suffix = options.suffix !== undefined ? options.suffix : '';
var countTo = function (timestamp) {
if (!startTime) startTime = timestamp;
var currentTime = timestamp - startTime;
var progress = currentTime / endTime;
progress = progress > 1 ? 1 : progress;
currentVal = options.startVal + (options.endVal - options.startVal) * _this.easing(progress);
currentVal = parseFloat(currentVal.toFixed(decimalPlaces));
if (elem) elem.innerHTML = prefix + _this.formatNumber(currentVal) + suffix;
if (progress < 1) reqAnimationFrame(countTo);
if (progress === 1 && options.onComplete) options.onComplete();
};
reqAnimationFrame(countTo);
}
_this.easing = options.easingFn || function (t) {
return --t * t * t + 1;
};
_this.formatNumber = function (num) {
num = num.toFixed(options.decimalPlaces);
num = num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return num;
};
}
在这个代码段中,我们定义了一个CountUp对象,它的参数是一个选项对象,包括:
el
: DOM元素的id;startVal
: 开始计数的值;endVal
: 结束计数的值;duration
: 计数持续时间;prefix
: 数字前缀;suffix
: 数字后缀;decimalPlaces
: 小数点位数;easingFn
: 缓动函数;onComplete
: 计数结束回调函数。
在这个对象中,我们同样通过requestAnimationFrame方法来实现计数器的更新,并在计数结束之后删除计数节点。同时,我们提供了一个_easing私有函数来进行缓动运动。我们还提供了一个_formatNumber私有函数来添加千位分隔符并保留小数点位数。最后,我们暴露了一个start方法来启动计数器的计数。
以上就是制作自己的countUp.js插件的完整攻略,其中给出了两个示例说明。希望这些内容能够对你有所帮助。