number-flip-animation
Version:
Small typescript package for animating the change of a number using a flip/slide animation.
95 lines (94 loc) • 5.98 kB
JavaScript
var NumberFlip = /** @class */ (function () {
function NumberFlip(_a) {
var rootElement = _a.rootElement, _b = _a.durationSlide, durationSlide = _b === void 0 ? 1000 : _b, _c = _a.durationFade, durationFade = _c === void 0 ? 200 : _c, initialNumber = _a.initialNumber, _d = _a.animateInitialNumber, animateInitialNumber = _d === void 0 ? true : _d, _e = _a.numberFormatter, numberFormatter = _e === void 0 ? function (num) { return num.toString(); } : _e, _f = _a.decimalSeparator, decimalSeparator = _f === void 0 ? '.' : _f, _g = _a.thousandSeparator, thousandSeparator = _g === void 0 ? ',' : _g, _h = _a.wrapperClassname, wrapperClassname = _h === void 0 ? 'numberflip-digit-container' : _h, _j = _a.digitClassname, digitClassname = _j === void 0 ? 'numberflip-digit-container-value' : _j;
this.rootElement = rootElement;
this.durationSlide = durationSlide;
this.durationFade = durationFade;
this.numberFormatter = numberFormatter;
this.decimalSeparator = decimalSeparator;
this.thousandSeparator = thousandSeparator;
this.wrapperClassname = wrapperClassname;
this.digitClassname = digitClassname;
this.rootElement.style.display = 'flex';
if (initialNumber !== undefined) {
this.setNumber(initialNumber, animateInitialNumber);
}
}
NumberFlip.prototype.setNumber = function (num, animate) {
if (animate === void 0) { animate = true; }
this.adjustAmountOfDigitContainers(num);
this.setDigitInContainers(num, animate);
};
NumberFlip.prototype.adjustAmountOfDigitContainers = function (num) {
var numberOfDigits = this.getDigitsOfNumber(num).length;
var countOfDigitContainers = this.rootElement.getElementsByClassName(this.wrapperClassname).length;
// Create digit containers
while (countOfDigitContainers < numberOfDigits) {
this.rootElement.insertAdjacentHTML('beforeend', "<div class=\"".concat(this.wrapperClassname, "\">") +
/*
The span with visibility hidden is needed in order to make the parent element occupy enough space to display the digit.
Otherwise the parent would have a width and height of 0 due to the absolute position of the .numberflip-digit-container-value element
*/
"<span style=\"visibility: hidden;\">0</span>\n <div class=\"".concat(this.digitClassname, "\" style=\"transform: translateY(-100%);\">\n <span>9</span>\n <span>8</span>\n <span>7</span>\n <span>6</span>\n <span>5</span>\n <span>4</span>\n <span>3</span>\n <span>2</span>\n <span>1</span>\n <span>0</span>\n <span>").concat(this.decimalSeparator, "</span>\n <span>").concat(this.thousandSeparator, "</span>\n </div>\n </div>"));
countOfDigitContainers++;
}
// Remove unnecessary digit containers
if (countOfDigitContainers > numberOfDigits) {
var digitContainers = this.rootElement.getElementsByClassName(this.digitClassname);
var _loop_1 = function (i) {
var digitContainer = digitContainers[i].parentElement;
digitContainer.style.animationDuration = this_1.durationFade + 'ms';
digitContainer.style.animationName = 'numberflip-animation-fade-out';
// Wait for fade out animation to finish before removing the element
setTimeout(function () { return digitContainer.remove(); }, this_1.durationFade);
};
var this_1 = this;
for (var i = numberOfDigits; i < digitContainers.length; i++) {
_loop_1(i);
}
}
};
NumberFlip.prototype.setDigitInContainers = function (num, animate) {
var _this = this;
var digits = this.getDigitsOfNumber(num);
var digitContainers = this.rootElement.getElementsByClassName(this.digitClassname);
var _loop_2 = function (i) {
var digitContainer = digitContainers[i];
var digit = digits[i] === this_2.thousandSeparator ? -2 : digits[i] === this_2.decimalSeparator ? -1 : digits[i];
// typeof check needed for typescripts typechecker
if (typeof digit === 'number') {
var translate_1 = this_2.calculateTranslateY(digit);
setTimeout(function () {
var durationSlide = animate ? _this.durationSlide : 0;
digitContainer.style.transitionDuration = durationSlide + 'ms';
digitContainer.style.transform = "translateY(".concat(translate_1, "%)");
}, 0);
}
digitContainer.parentNode.classList[digits[i] === this_2.decimalSeparator || digits[i] === this_2.thousandSeparator ? 'add' : 'remove']('dot');
};
var this_2 = this;
for (var i = 0; i < digitContainers.length; i++) {
_loop_2(i);
}
};
NumberFlip.prototype.getDigitsOfNumber = function (num) {
var _this = this;
var digits = this.numberFormatter(num).split('');
return digits.map(function (char) {
if (char === _this.decimalSeparator) {
return _this.decimalSeparator;
}
else if (char === _this.thousandSeparator) {
return _this.thousandSeparator;
}
return parseInt(char, 10);
});
};
NumberFlip.prototype.calculateTranslateY = function (digit) {
// 12 is the number of span elements defined above in the adjustAmountOfDigitContainers method
var heightOfSpan = 100 / 12;
return (-10 * heightOfSpan + (digit + 1) * heightOfSpan).toString();
};
return NumberFlip;
}());
export { NumberFlip };