Button gradient animation

Button gradient animation

by Boba Poshtar

HTML

<p><a href="#" class="btn noanim">without animation background</a></p>
<p><a href="#" class="btn">with animation background</a></p>
<p><a href="#" class="btn">with animation background</a></p>

CSS

p { text-align: center; }
.btn {
	display: inline-block;
	padding: 18px 75px;
	color: #fff;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 24px;
	line-height: 30px;
	text-decoration: none;
	background: #23b9e2 linear-gradient(to right, #07a7dd, #43cee7);
	border: none;
	border-radius: 33px;
	box-shadow: 0 10px 25px rgba(0, 0, 0, .2);
	transition: background 1s ease;
}
.btn:hover {
	color: #fff;
}
.btn.noanim:hover {
	background: #2bbde0 linear-gradient(to right, #65d5ce, #38aec2);
}

JavaScript

document.querySelectorAll('a').forEach(function(a){
	a.onclick = function(){ return false };
});

(function(){
	let btnDuration = 400;
	let bClors = {
		c1: { r: 7, g: 167, b: 221 },
		c2: { r: 67, g: 206, b: 231 },
		c1h: { r: 101, g: 213, b: 206 },
		c2h: { r: 56, g: 174, b: 194 }
	};
	function stopAnim($button){
		clearInterval(parseInt($button.dataset.tid));
	}
	function setGradient($button, t){
		function calcColor(n, c, p){
			return Math.round((bClors['c' + n + 'h'][c] - bClors['c' + n][c]) * p + bClors['c' + n][c]);
		}
		$button.dataset.timer = t;
		let p = t / btnDuration;
		let c1 = calcColor(1, 'r', p) + ', ' + calcColor(1, 'g', p) + ', ' + calcColor(1, 'b', p);
		let c2 = calcColor(2, 'r', p) + ', ' + calcColor(2, 'g', p) + ', ' + calcColor(2, 'b', p);
		$button.style.backgroundImage = 'linear-gradient(to right, rgb(' + c1 + '), rgb(' + c2 + '))';
	}
	document.querySelectorAll('.btn').forEach(function($button){
		if ($button.classList.contains('noanim')) return;
		function changeGradient(e){
			let k = e.type === 'mouseenter';
			if (!this.dataset.timer) this.dataset.timer = k ? 0 : btnDuration;
			if (this.dataset.tid) stopAnim(this);
			this.dataset.tid = setInterval(function($button){
				let t = parseInt($button.dataset.timer) + (k ? 20 : -20);
				setGradient($button, t);
				if (k && t >= btnDuration || !k && t <=0) stopAnim($button);
			}, 20, this);
		};
		$button.onmouseenter = changeGradient;
		$button.onmouseleave = changeGradient;
	});
})();