JSFiddle - React, Tailwind, and code Playground

by Dmytriy_od

HTML

<div class="project">
	<div id="gradient" class="gradient"></div>
	<span>Текст</span>
</div>

CSS

.project {
	background-image: linear-gradient(rgba(0, 0, 0, 0.39), rgba(0, 0, 0, 0.39)), url("https://cdn.pixabay.com/photo/2018/03/11/20/42/mammals-3218028_960_720.jpg");
	width: 400px;
	height: 200px;
	position: relative;
	overflow: hidden;
	display: flex;
}

.project span {
	display: block;
	position: relative;
	z-index: 3;
	margin: auto;
	color: #fff;
	font-size: 18px;
	pointer-events: none;
}

.project::after {
	content: '';
	transition: opacity .35s, visibility .35s, transform .35s;
	display: block;
	position: absolute;
	width: 100%;
	height: 100%;
	top: 0%;
	left: 0;
	opacity: 0;
	transform: scaleY(0);
}

.project-1:hover::after {
	transform: scaleY(1);
	opacity: 1;
}

.gradient {
	transform: scaleY(0);
	transition: opacity .35s, visibility .35s, transform .35s;
	z-index: 1;
	height: calc(100% * 3);
	background: linear-gradient(180deg, #eb03f9, #02d1f6);
	position: absolute;
	width: 100%;
	height: 100%;
}

.project:hover .gradient {
	transform: scaleY(1);
}

JavaScript

class rotationOfTheObjectTowardsTheCursor {

	constructor() {
		this.container = Object;
		this.gradient = Object;
		
		this.containerRect = Object;
		
		this.centerPosition = { x: 0, y: 0 };
		this.angels = { actual: 0, target: 0 };
		
		this.init();
	}
	
	init() {
		this.container = document.querySelector('.project');
		this.gradient = document.querySelector('.gradient');
		
		this.onResize();
		window.onresize = (e) => this.onResize(e);
		
		window.onmousemove = (e) => this.onMouseMove(e);
		
		requestAnimationFrame(() => this.loop());
	}
	
	onResize() {
		this.containerRect = this.container.getBoundingClientRect();
		this.centerPosition = {
			x: this.containerRect.x + this.containerRect.width / 2,
			y: this.containerRect.y + this.containerRect.height / 2,
		};
	}
	
	onMouseMove(e) {
		const atan2 = Math.atan2(
			e.pageY - this.centerPosition.y,
			e.pageX - this.centerPosition.x
		);
		
		this.angels.target = atan2;
	}
	
	loop() {
		this.angels.actual = this.angleLerp(
			this.angels.actual,
			this.angels.target,
			0.05
		);
		this.gradient.style.background = `linear-gradient(${this.angels.actual + 90}rad, #02d1f6, #eb03f9)`;

		requestAnimationFrame(() => this.loop());
	}
	
	angleLerp(a0, a1, t) {
		const max = Math.PI * 2;
		const da = (a1 - a0) % max;
		return a0 + (((2 * da) % max) - da) * t;
	}

}

new rotationOfTheObjectTowardsTheCursor();