<canvas></canvas>
html,
body {
	width: 100%;
	height: 100%;
	overflow: hidden;
}

body {
	margin: 0;
	padding: 0;
	color: #fff;
	background-color: #000;
}

canvas {
	-webkit-tap-highlight-color: transparent;
	tap-highlight-color: transparent;
	-webkit-user-select: none;
	user-select: none;
	cursor: pointer;
}
// Wobble by @neave

window.requestAnimationFrame =
	window.requestAnimationFrame ||
	window.webkitRequestAnimationFrame ||
	window.mozRequestAnimationFrame ||
	window.msRequestAnimationFrame ||
	function(callback) {
		setTimeout(callback, 1000 / 60);
	};

Array.prototype.shuffle = function() {
	var j, temp;
	for (var i = this.length - 1; i > 0; i--) {
		j = Math.floor(Math.random() * (i + 1));
		temp = this[i];
		this[i] = this[j];
		this[j] = temp;
	}
	return this;
};

Math.clamp = function(n, min, max) {
	return Math.max(min, Math.min(n, max));
};

var get = document.querySelector.bind(document),
	on = document.addEventListener.bind(document),
	mouseOff = -1000,
	mouseX,
	mouseY,
	viscosity = 25,
	damping = 0.1,
	totalPoints,
	dist,
	scale,
	canvas,
	context,
	surfaces,
	palleteNum = 0,
	palleteFirst = ['0cf', '0fc', 'ff0', 'f0c', 'c0f'],
	palletes = [
		['000', 'ff0', 'f0f', '0ff', 'fff'],
		['000', 'fff', '000', 'fff', '000'],
		['333', '666', '999', 'ccc', 'fff'],
		['300', '600', 'f00', '600', '300'],
		['305', '606', '907', 'c08', 'f09'],
		['036', '067', '098', '0c9', '0fa'],
		['00a0b0', '6a4a3c', 'cc333f', 'eb6841', 'edc951'],
		['264653', '2a9d8f', 'e9c46a', 'f4a261', 'e76f51'],
		['300018', '5a3d31', '837b47', 'adb85f', 'e5edb8'],
		['343838', '005f6b', '008c9e', '00b4cc', '00dffc'],
		['3fb8af', '7fc7af', 'dad8a7', 'ff9e9d', 'ff3d7f'],
		['413e4a', '73626e', 'b38184', 'f0b49e', 'f7e4be'],
		['452632', '91204d', 'e4844a', 'e8bf56', 'e2f7ce'],
		['594f4f', '547980', '45ada8', '9de0ad', 'e5fcc2'],
		['5d4157', '838689', 'a8caba', 'cad7b2', 'ebe3aa'],
		['81657e', '3ea3af', '9fd9b3', 'f0f6b9', 'ff1d44'],
		['899aa1', 'bda2a2', 'fbbe9a', 'fad889', 'faf5c8'],
		['99b898', 'fecea8', 'ff847c', 'e84a5f', '2a363b'],
		['ab526b', 'bca297', 'c5ceae', 'f0e2a4', 'f4ebc3'],
		['acdeb2', 'e1eab5', 'edad9e', 'fe4b74', '390d2d'],
		['b9d7d9', '668284', '2a2829', '493736', '7b3b3b'],
		['bbbb88', 'ccc68d', 'eedd99', 'eec290', 'eeaa88'],
		['cff09e', 'a8dba8', '79bd9a', '3b8686', '0b486b'],
		['d1f2a5', 'effab4', 'ffc48c', 'ff9f80', 'f56991'],
		['d3e2b6', 'c3dbb4', 'aaccb1', '87bdb1', '68b3af'],
		['e0ffb3', '61c791', '31797d', '2a2f36', 'f23c55'],
		['e25858', 'e9d6af', 'ffffdd', 'c0efd2', '384252'],
		['e8608c', '71cbc4', 'fff9f4', 'cdd56e', 'ffbd68'],
		['e8ddcb', 'cdb380', '036564', '033649', '031634'],
		['e94e77', 'd68189', 'c6a49a', 'c6e5d9', 'f4ead5'],
		['eee6ab', 'c5bc8e', '696758', '45484b', '36393b'],
		['efffcd', 'dce9be', '555152', '2e2633', '99173c'],
		['f04155', 'ff823a', 'f2f26f', 'fff7bd', '95cfb7'],
		['f8b195', 'f67280', 'c06c84', '6c5b7b', '355c7d'],
		['f8f4d7', 'f4dec2', 'f2b4a8', 'e98977', 'f4b36c'],
		['fad089', 'ff9c5b', 'f5634a', 'ed303c', '3b8183'],
		['fe4365', 'fc9d9a', 'f9cdad', 'c8c8a9', '83af9b'],
		['ff4e50', 'fc913a', 'f9d423', 'ede574', 'e1f5c4'],
		['ff9900', '424242', 'e9e9e9', 'bcbcbc', '3299bb'],
		['ffed90', 'a8d46f', '359668', '3c3251', '341139']
	];

function Point(x, y) {
	this.x = x;
	this.y = y;

	this.ix = x;
	this.iy = y;

	this.vx = 0;
	this.vy = 0;
}

Point.prototype.move = function() {
	var width = canvas.width / scale;
	var height = canvas.height / scale;
	this.vx += (this.ix - this.x) / viscosity * width;
	this.vy += (this.iy - this.y) / viscosity * height;

	var dx = this.x * width - mouseX / scale,
		dy = this.y * height - mouseY / scale;

	if (Math.sqrt(dx * dx + dy * dy) < dist) {
		var a = Math.atan2(dy, dx);
		this.vx += (Math.cos(a) * viscosity - dx) / viscosity;
		this.vy -= (Math.sin(a) * viscosity - dy) / viscosity;
	}

	this.vx *= (1 - damping);
	this.vy *= (1 - damping);
	this.x += this.vx / width;
	this.y += this.vy / height;

	if (this.y < 0) {
		this.y = 0;
	} else if (this.y > 1) {
		this.y = 1;
	}
};

function Surface(y) {
	this.y = y;
	this.resize();
}

Surface.prototype.draw = function() {
	var p = this.points[totalPoints - 1],
		cx,
		cy;

	context.fillStyle = this.color;
	context.beginPath();
	context.moveTo(p.x * canvas.width, p.y * canvas.height);

	for (var i = totalPoints - 1; i > 0; i--) {
		p = this.points[i];
		p.move();

		cx = (p.x + this.points[i - 1].x) / 2 * canvas.width;
		cy = (p.y + this.points[i - 1].y) / 2 * canvas.height;

		if (i === 1) {
			cx = canvas.width;
		} else if (i === totalPoints - 1) {
			context.bezierCurveTo(p.x * canvas.width, p.y * canvas.height, cx, cy, cx, cy);
			p.x = 0;
		}

		context.bezierCurveTo(p.x * canvas.width, p.y * canvas.height, cx, cy, cx, cy);
	}

	context.lineTo(canvas.width, canvas.height);
	context.lineTo(0, canvas.height);
	context.closePath();
	context.fill();
};

Surface.prototype.resize = function() {
	this.points = [];
	for (var i = totalPoints; i--; ) {
		this.points.push(new Point(i / (totalPoints - 3), this.y));
	}
};

Surface.prototype.wobble = function() {
	for (var i = totalPoints - 1; i > 0; i--) {
		this.points[i].vy += (Math.random() - 0.5) * dist * 0.6;
	}
};

function setPallete() {
	canvas.style.backgroundColor = '#' + palletes[palleteNum][0];
	for (var i = surfaces.length; i--; ) {
		surfaces[surfaces.length - i - 1].color = '#' + palletes[palleteNum][i + 1];
	}
}

function nextPallete() {
	palleteNum++;
	if (palleteNum >= palletes.length) {
		palleteNum = 0;
		palletes.shuffle();
	}
	setPallete();
}

function wobbleSuraces() {
	resizeSuraces();

	for (var i = surfaces.length; i--; ) {
		surfaces[i].wobble();
	}
	nextPallete();
}

function drawSurfaces() {
	context.clearRect(0, 0, canvas.width, canvas.height);
	for (var i = surfaces.length; i--; ) {
		surfaces[i].draw();
	}
}

function resizeSuraces() {
	scale = window.devicePixelRatio || 1;

	canvas.width = innerWidth * scale;
	canvas.height = innerHeight * scale;
	canvas.style.width = innerWidth + 'px';
	canvas.style.height = innerHeight + 'px';

	totalPoints = Math.round(Math.clamp(Math.pow(Math.random() * 8, 2), 16, innerWidth / 35));
	dist = Math.clamp(innerWidth / 4, 150, 200);

	for (var i = surfaces.length; i--; ) {
		surfaces[i].resize();
	}
	drawSurfaces();
}

function update() {
	requestAnimationFrame(update);
	drawSurfaces();
}

function init() {
	canvas = get('canvas');
	context = canvas.getContext('2d');

	canvas.ontouchmove = function(event) {
		mouseX = event.targetTouches[0].pageX * scale;
		mouseY = event.targetTouches[0].pageY * scale;
	};

	canvas.ontouchstart = function(event) {
		event.preventDefault();
	};

	canvas.ontouchend = function(event) {
		wobbleSuraces();
		mouseX = mouseY = mouseOff;
	};

	canvas.onmousemove = function(event) {
		mouseX = event.pageX * scale;
		mouseY = event.pageY * scale;
	};

	canvas.onmousedown = wobbleSuraces;

	canvas.onmouseleave = function() {
		mouseX = mouseY = mouseOff;
	};

	surfaces = [
		new Surface(4/5),
		new Surface(3/5),
		new Surface(2/5),
		new Surface(1/5)
	];

	palletes.shuffle();
	palletes.unshift(palleteFirst);
	setPallete(0);

	window.onresize = resizeSuraces;
	resizeSuraces();
	update();
}

on('DOMContentLoaded', init);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.