Hiệu ứng theo chuột với JavaScript

0

Hôm nay chúng ta sẽ vui vẻ một chút cùng JavaScript. Với hiệu ứng theo chuột này các bạn sẽ cảm nhận được rõ ràng sự chuyển động khi bạn thao tác với con chuột máy tính. Cụ thể, chúng ta sẽ có hai hiệu ứng: Khi bạn Click thì màu sắc sẽ được thay đổi, khi bạn di chuyển con chuột thì các phần tử trong đó sẽ theo con chuột tới cùng trời cuối đất.

Hiệu ứng theo chuột với JavaScript Hiệu ứng theo chuột - Hiệu ứng theo chuột với JavaScript

Để sử dụng hiệu ứng này các bạn cần đoạn HTML sau:

<canvas id="canvas"></canvas>
<p>
	<strong>Thay đổi tỷ trọng:</strong> Di chuyển chuột<br>
	<strong>Thay đổi màu sắc:</strong> Click chuột
</p>

Bên trên chúng ta chỉ cần thẻ canvas thôi. Các đoạn trong thẻ P là được sử dụng để ghi chú. Và tiếp theo chúng ta sẽ cần đến đoạn Code CSS này:

body {
	overflow: hidden;	
}

canvas {
	left: 0;
	position: absolute;
	top: 0;
}

p {
	background: rgba(0, 0, 0, 0.5);
	color: #fff;
	left: 0;
	font-family: sans-serif;
	font-size: 14px;
	line-height: 1.5;
	margin: 0;
	padding: 20px 30px;
	position: absolute;
	top: 0;
}

Linh hồn cho bài viết này nằm ở đoạn JavaScript dưới đây:

var canvas,
	ctx,
	width,
	height,
	xGravity,
	yGravity,
	friction,
	dots,
	palettes,
	paletteCount,
	paletteCurrent,
	colorCount,
	tick,
	mx,
	my,
	PI,
	TWOPI;

function rand( min, max ) {
	return Math.random() * ( max - min ) + min;
}

function randInt( min, max ) {
	return Math.floor( min + Math.random() * ( max - min + 1 ) );
};

function Dot() {
	this.x = width / 2;
	this.y = height / 2;
	this.vx = rand( -2, 2 );
	this.vy = rand( -2, 2 );
	this.radius = rand( 5, 15 );
	this.color = randInt( 1, colorCount - 1 );
}

Dot.prototype.step = function( i ) {
	// apply forces	
	this.x += this.vx;
	this.y += this.vy;
		
	// handle bounce	
	if( this.vx > 0 && this.x + this.radius >= width ) {
		this.vx *= -0.6;
	}
	
	if( this.vx < 0 && this.x - this.radius <= 0 ) {
		this.vx *= -0.6;
	}
	
	if( this.vy > 0 && this.y + this.radius >= height ) {
		this.vy *= -0.6;
	}
	
	if( this.vy < 0 && this.y - this.radius <= 0 ) {
		this.vy *= -0.6;
	}
	
	// handle bounds and friction	
	if( this.x + this.radius > width ) {
		this.x = width - this.radius;
		this.vy *= friction;
	}
	
	if( this.x - this.radius < 0 ) {
		this.x = this.radius;
		this.vy *= friction;
	}
	
	if( this.y + this.radius > height ) {
		this.y = height - this.radius;
		this.vx *= friction;
	}
	
	if( this.y - this.radius < 0 ) {
		this.y = this.radius;
		this.vx *= friction;
	}
	
	// handle gravity	
	this.vx += xGravity;
	this.vy += yGravity;
};

Dot.prototype.collide = function( otherDot ) {
	// still working on understanding this
	// lots of help from http://lamberta.github.io/html5-animation/
	var dx = otherDot.x - this.x,
		dy = otherDot.y - this.y,
		dist = Math.sqrt( dx * dx + dy * dy ),
		minDist = this.radius + otherDot.radius;
	if( dist < minDist ) {
		var tx = this.x + dx / dist * minDist,
			ty = this.y + dy / dist * minDist,
			ax = ( tx - otherDot.x ) * 0.6,
			ay = ( ty - otherDot.y ) * 0.6;
		this.vx -= ax;
		this.vy -= ay;      
		otherDot.vx += ax;
		otherDot.vy += ay;
		this.vx *= friction * 0.9;
		this.vy *= friction * 0.9;
		otherDot.vx *= friction * 0.9;
		otherDot.vy *= friction * 0.9;
	}
};

Dot.prototype.draw = function() {
	ctx.beginPath();
	ctx.arc( this.x, this.y, this.radius, 0, TWOPI );
	ctx.fillStyle = palettes[ paletteCurrent ][ this.color ];
	ctx.fill();
};

function init() {
	canvas = document.getElementById( 'canvas' );
	ctx = canvas.getContext( '2d' );
	xGravity = 0;
	yGravity = 1;
	friction = 0.99;
	dots = [];
	// palette credits:
	// https://color.adobe.com/Friends-and-foes-color-theme-1175537/
	// https://color.adobe.com/Ocean-Sunset-color-theme-46355/
	// https://color.adobe.com/Gettysburg-color-theme-209416/
	// https://color.adobe.com/vintage-card-color-theme-3165833/
	palettes = [
		[
			'#2e2932',
			'#01a2a6',
			'#37d8c2',
			'#bdf271',
			'#ffffa6'
		],
		[
			'#405952',
			'#9c9b7a',
			'#ffd393',
			'#ff974f',
			'#f35033'
		],
		[
			'#962d3e',
			'#343641',
			'#979c9c',
			'#f2ebc9',
			'#388898'
		],
		[
			'#f2ebbf',
			'#5c4b51',
			'#8dbeb2',
			'#f2b468',
			'#ee6163'
		]
	];
	paletteCount = palettes.length;
	paletteCurrent = 3;	
	colorCount = palettes[ 0 ].length;
	PI = Math.PI;
	TWOPI = PI * 2;
	
	reset();
	loop();
}

function reset() {
	width = window.innerWidth;
	height = window.innerHeight;
	dots.length = 0;
	tick = 0;
	mx = width / 2;
	my = height / 2;
	
	canvas.width = width;
	canvas.height = height;
}

function create() {
	if( tick && dots.length < 500 ) {
		dots.push( new Dot() );	
	}
}

function step() {
	var i = dots.length;
	while( i-- ) {
		dots[ i ].step( i );	
	}
	
	i = dots.length;
	while( i-- ) {
		dot = dots[ i ];
		var j = i;
		if( j > 0 ) {
			while( j-- ) {
				dot.collide( dots[ j ] );
			}
		}
	}
}

function draw() {
	ctx.fillStyle = palettes[ paletteCurrent ][ 0 ];
	ctx.fillRect( 0, 0, width, height );
	
	var i = dots.length;
	while( i-- ) {
		dots[ i ].draw();	
	}
}

function loop() {
	requestAnimationFrame( loop );
	create();
	step();
	draw();
	tick++;
}

function onmousemove( e ) {
	mx = e.pageX;
	my = e.pageY;
	
	xGravity = ( mx - width / 2 ) / ( width / 2 );
	yGravity = ( my - height / 2 ) / ( height / 2 );
}

function onmousedown() {
	var i = dots.length;
	while( i-- ) {
		dots[ i ].vx += rand( -10, 10 );
		dots[ i ].vy += rand( -10, 10 );
	}

	if( paletteCurrent < paletteCount - 1 ) {
		paletteCurrent++;	
	} else {
		paletteCurrent = 0;	
	}
}

window.addEventListener( 'resize', reset );
window.addEventListener( 'mousemove', onmousemove );
window.addEventListener( 'mousedown', onmousedown );

init();

Xong rồi đấy, ngay bây giờ mời các bạn cùng Demo :

See the Pen Follow mouse with JavaScript effects by Lại Văn Đức (@laivanduc) on CodePen.16775

Để lại một trả lời

Địa chỉ email của bạn sẽ không được công bố.