Animated Number Counter



Hiệu ứng số nhảy tự động được chỉ định bằng Javascript

1. HTML

section.counters
	h3.counter(aria-label="$65.3M") $65.3M
	h3.counter(aria-label="872K") 872K
	h3.counter(aria-label="$491") $491
	h3.counter(aria-label="9875") 9875

2. CSS

.counters {
	display: flex;
	background: rgba($white, 0.75);
	padding: 20px;
	border-radius: 10px;
	box-shadow: 5px 5px 20px rgba($black, 0.2);
}

.counter {
	letter-spacing: rem(2px);
	line-height: 1;
	position: relative;
	display: flex;
	overflow: hidden;
	align-items: center;
	height: rem(50px);
	font-size: rem(50px);
	margin: 0 rem(20px);
	font-weight: 400;
	& > span {
		z-index: 1;
		display: flex;
		flex-direction: column;
		height: 100%;
		transition: transform 2s ease;
		transform: translateY(0);
		line-height: 1;
		span {
			flex: 0 0 100%;
			height: 100%;
		}
	}
	$d: 0;
	$inc: 0.375;
	@for $i from 1 through 20 {
		&:nth-child(#{$i}) > span {
			transition-delay: #{$d * 1s};
		}
		$d: $d + $inc;
	}
}



.counter:nth-child(1) {
	color: #EF8354;
}
.counter:nth-child(2) {
	color: #0EB1D2;
}
.counter:nth-child(3) {
	color: #2D3142;
}
.counter:nth-child(4) {
	color: #698F3F;
}

3. JAVASCRIPT

const stats = document.querySelectorAll(".counter");

stats.forEach(stat => {
	// pattern used to seperate input number from html into an array of numbers and non numbers. EX $65.3M -> ["$65.3M", "$", "65", ".", "3", "M"]
	const patt = /(\D+)?(\d+)(\D+)?(\d+)?(\D+)?/;
	const time = 1000;
	let result = [...patt.exec(stat.textContent)];
	let fresh = true;
	let ticks;

	// Remove first full match from result array (we dont need the full match, just the individual match groups).
	result.shift();
	// Remove undefined values from result array where they didnt have a match in one of the optional regex groups
	result = result.filter(res => res != null);

	while (stat.firstChild) {
		stat.removeChild(stat.firstChild);
	}

	for (let res of result) {
		if (isNaN(res)) {
			stat.insertAdjacentHTML("beforeend", `${res}`);
		} else {
			for (let i = 0; i < res.length; i++) {
				stat.insertAdjacentHTML(
					"beforeend",
					`
						
						${Array(parseInt(res[i]) + 1)
							.join(0)
							.split(0)
							.map(
								(x, j) => `
							${j}
						`
							)
							.join("")}
					`
				);
			}
		}
	}

	ticks = [...stat.querySelectorAll("span[data-value]")];

	let activate = () => {
		let top = stat.getBoundingClientRect().top;
		let offset = window.innerHeight * 3 / 4;

		setTimeout(() => {
			fresh = false;
		}, time);

		if (top < offset) {
			setTimeout(() => {
				for (let tick of ticks) {
					let dist = parseInt(tick.getAttribute("data-value")) + 1;
					tick.style.transform = `translateY(-${dist * 100}%)`;
				}
			}, fresh ? time : 0);
			window.removeEventListener("scroll", activate);
		}
	};
	window.addEventListener("scroll", activate);
	activate();
});



Mong bài viết giúp ích được các bạn phần nào trong thiết kế Web. Hãy nhấn nút để mọi người cùng học hỏi kiến thức mới nhé. Cảm ơn các bạn đã quan tâm Forum.