A Pen by Łukasz Zembrzuski

Thumbnail
This awesome code was written by zembrzuski, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright zembrzuski ©
  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>A Pen by  Łukasz Zembrzuski</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div class="lol"> lorem ipsum </div>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/zembrzuski/a-pen-by-andx141ukasz-zembrzuski-wXMMjR */
body
{
  background-color:white; 
}
.lol{
  padding-bottom:1600px;
}

/*Downloaded from https://www.codeseek.co/zembrzuski/a-pen-by-andx141ukasz-zembrzuski-wXMMjR */
(function(global) {
	var bubbleTrail = function(options) {
		return new bubbleTrail.init(options);
	};

	bubbleTrail.prototype = {
		initialised: false,
		paused: false,
		index: 0,
		bubbleStore: [],

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

		setTransition: function(bubble) {
			var self = this;
			bubble.style.visibility = "visible";
			bubble.style.opacity = "1";
			bubble.style.webkitTransitionProperty = "all";
			bubble.style.transitionDuration = self.duration + "s";
			bubble.style.transitionTimingFunction = "cubic-bezier(0,0,1,1)";
		},

		removeTransition: function(bubble) {
			bubble.style.visibility = "hidden";
			bubble.style.transform = "scale(1)";
			bubble.style.webkitTransitionProperty = "";
			bubble.style.transitionDuration = "";
			bubble.style.transitionTimingFunction = "";
			bubble.used = false;
		},

		createBubble: function(x, y) {
			var self = this,
				bubbleSize =
					self.bubbleSizes[
						Math.floor(self.createRandomNumber(0, self.bubbleSizes.length))
					],
				bubbleColour =
					self.bubbleColours[
						Math.floor(self.createRandomNumber(0, self.bubbleColours.length))
					],
				bubble = document.createElement("span");

			bubble.style.width = bubbleSize;
			bubble.style.height = bubbleSize;
			bubble.style.background = bubbleColour;
			bubble.style.visibility = "hidden";
			bubble.style.position = "fixed";
			bubble.style.borderRadius = "50%";
			self.setDynamicBubbleAttributes(bubble, x, y);
			bubble.used = false;
			document.querySelector("body").appendChild(bubble);
			return bubble;
		},

		setDynamicBubbleAttributes: function(bubble, x, y) {
			bubble.style.top = y + "px";
			bubble.style.left = x + "px";
			bubble.style.transform = "scale(1)";
			bubble.style.opacity = "1";
		},

		animateBubble: function(bubble) {
			var self = this;

			setTimeout(function() {
				var randomTopPos = self.createRandomNumber(
						Number(bubble.style.top.slice(0, -2)) - 10,
						Number(bubble.style.top.slice(0, -2)) + 300
					),
					randomLeftPos =
						self.createRandomNumber(
							Number(bubble.style.left.slice(0, -2)) - 50,
							Number(bubble.style.left.slice(0, -2))
						) + 50;
				self.setTransition(bubble);
				bubble.style.top = randomTopPos + "px";
				bubble.style.left = randomLeftPos + "px";
				bubble.style.opacity = "0";
				bubble.style.transform = "scale(0)";
			}, 40);

			setTimeout(function() {
				self.removeTransition(bubble);
			}, self.removeDuration);
		},

		initAnimation: function(x, y, i) {
			var self = this;
			self.setDynamicBubbleAttributes(self.bubbleStore[i], x, y);
			self.animateBubble(self.bubbleStore[i]);
			self.bubbleStore[i].used = true;
		},

		updateColours: function(colours) {
			if (!Array.isArray(colours)) throw "Colours must be stored in an array";
			var self = this;
			for (var i = 0; i < self.bubbleStore.length; i++) {
				var bubbleColour =
					colours[Math.floor(self.createRandomNumber(0, colours.length))];
				self.bubbleStore[i].style.background = bubbleColour;
			}
			return self;
		},

		initMousemove: function() {
			var self = this;
			global.addEventListener("mousemove", function(e) {
				// Pozycja kursora
				var evnt = e,
					cursorX = event.clientX;
						
						
					cursorY = event.clientY;
					
							
				// check bubbletrail isn't paused and index is less than the bubbles available
				if (self.index < self.bubbleStore.length && !self.paused) {
					var foundOne = false;
					// while a unused bubble hasn't been found and the index is less than bubbles available
					// loop through bubbles
					while (!foundOne && self.index < self.bubbleStore.length) {
						// check for the first available unused bubble
						if (!self.bubbleStore[self.index].used) {
							// animate bubble
							self.initAnimation(cursorX, cursorY, self.index);
							self.index++;
							// set bubble to used
							foundOne = true;
							break;
						} else {
							self.index++;
						}
					}
				} else {
					self.index = 0;
				}
				evnt.stopPropagation();
			});
		},

		initTouchmove: function() {
			var self = this;
			global.addEventListener("touchmove", function(e) {
				// config
				var evnt = e,
					cursorX = evnt.targetTouches[0].pageX,
					cursorY = evnt.targetTouches[0].pageY;

				if (self.index < self.bubbleStore.length && !self.paused) {
					var foundOne = false;
					while (!foundOne && self.index < self.bubbleStore.length) {
						if (!self.bubbleStore[self.index].used) {
							self.initAnimation(cursorX, cursorY, self.index);
							self.index++;
							foundOne = true;
							break;
						} else {
							self.index++;
						}
					}
				} else {
					self.index = 0;
				}
				evnt.stopPropagation();
			});
		},

		start: function() {
			var self = this;

			if (!self.initialised) {
				for (var i = 0; i < self.numBubbles; i++) {
					self.bubbleStore.push(self.createBubble(0, 0));
				}
				self.initMousemove();
				self.initTouchmove();
				self.initialised = true;
			} else {
				throw "bubbleTrail can only be started once";
			}
			return self;
		},

		pause: function() {
			var self = this;
			if (!self.paused) self.paused = true;
			return self;
		},

		resume: function() {
			var self = this;
			if (self.paused) self.paused = false;
			return self;
		}
	};

	bubbleTrail.init = function(options) {
		var self = this,
			options = options || {};
		// test options props are valid
		if (options.colours && !Array.isArray(options.colours))
			throw "Colours must be stored in an array";
		if (options.sizes && !Array.isArray(options.sizes))
			throw "Sizes must be stored in an array";
		if (options.numBubbles && typeof options.numBubbles !== "number")
			throw "numBubbles must be an integer";
		// setup options
		self.bubbleColours = options.colours || ["#df2b4f", "#32adad", "#ffa500"];
		self.bubbleSizes = options.sizes || ["4px", "5px", "6px", "10px"];
		self.speed = options.speed || "fast";
		self.numBubbles =
			self.speed === "fast"
				? 100
				: self.speed === "medium" ? 200 : self.speed === "slow" ? 500 : 100;
		self.duration =
			self.numBubbles === 100
				? 0.7
				: self.numBubbles === 200 ? 1.2 : self.numBubbles === 300 ? 1.8 : 0.7;
		self.removeDuration = self.duration * 1000;
	};

	bubbleTrail.init.prototype = bubbleTrail.prototype;
	global.bubbleTrail = bubbleTrail;
})(window);

var options = {
	colours: ["#7f1a1a"], // as many colours as you want
	sizes: ["12px","11px","10px","9px","0px","0px"], // as many sizes as you want
	speed: "slow" // 'fast' , 'medium' , 'slow'
};

var bubbleTrail = bubbleTrail(options).start();

// bubbleTrail.pause();
// bubbleTrail.resume();
// bubbleTrail.updateColours(['#ff6f69', 'orange', '#88d8b0', '#ffeead']);

Comments