// Constants const element = document.documentElement, body = document.body, revealOnScroll = (window.sr = ScrollReveal({ mobile: false })); // Load animations element.classList.remove("no-js"); element.classList.add("js"); window.addEventListener("load", function () { body.classList.add("is-loaded"); }); if (body.classList.contains("has-animations")) { window.addEventListener("load", function () { revealOnScroll.reveal(".feature-extended .device-mockup", { duration: 600, distance: "100px", easing: "cubic-bezier(0.215, 0.61, 0.355, 1)", origin: "bottom", viewFactor: 0.6, }); revealOnScroll.reveal(".feature-extended .feature-extended-body", { duration: 600, distance: "40px", easing: "cubic-bezier(0.215, 0.61, 0.355, 1)", origin: "top", viewFactor: 0.6, }); }); } // Bubble canvas let bubbleCanvas = function (t) { let e = this; e.parentNode = t; e.setCanvasSize(); window.addEventListener("resize", function () { e.setCanvasSize(); }); e.mouseX = 0; e.mouseY = 0; window.addEventListener("mousemove", function (t) { (e.mouseX = t.clientX), (e.mouseY = t.clientY); }); e.randomise(); }; bubbleCanvas.prototype.setCanvasSize = function () { this.canvasWidth = this.parentNode.clientWidth; this.canvasHeight = this.parentNode.clientHeight; }; bubbleCanvas.prototype.generateDecimalBetween = function (start, end) { return (Math.random() * (start - end) + end).toFixed(2); }; bubbleCanvas.prototype.update = function () { let t = this; t.translateX = t.translateX - t.movementX; t.translateY = t.translateY - t.movementY; t.posX += (t.mouseX / (t.staticity / t.magnetism) - t.posX) / t.smoothFactor; t.posY += (t.mouseY / (t.staticity / t.magnetism) - t.posY) / t.smoothFactor; if ( t.translateY + t.posY < 0 || t.translateX + t.posX < 0 || t.translateX + t.posX > t.canvasWidth ) { t.randomise(); t.translateY = t.canvasHeight; } }; bubbleCanvas.prototype.randomise = function () { this.colors = ["195,53,46", "172,54,46"]; this.velocity = 20; this.smoothFactor = 50; this.staticity = 30; this.magnetism = 0.1 + 4 * Math.random(); this.color = this.colors[Math.floor(Math.random() * this.colors.length)]; this.alpha = this.generateDecimalBetween(5, 10) / 10; this.size = this.generateDecimalBetween(1, 4); this.posX = 0; this.posY = 0; this.movementX = this.generateDecimalBetween(-2, 2) / this.velocity; this.movementY = this.generateDecimalBetween(1, 20) / this.velocity; this.translateX = this.generateDecimalBetween(0, this.canvasWidth); this.translateY = this.generateDecimalBetween(0, this.canvasHeight); }; let drawBubbleCanvas = function (t) { this.canvas = document.getElementById(t); this.ctx = this.canvas.getContext("2d"); this.dpr = window.devicePixelRatio; }; drawBubbleCanvas.prototype.start = function (bubbleDensity) { let t = this; t.bubbleDensity = bubbleDensity; t.setCanvasSize(); window.addEventListener("resize", function () { t.setCanvasSize(); }); t.bubblesList = []; t.generateBubbles(); t.animate(); }; drawBubbleCanvas.prototype.setCanvasSize = function () { this.container = this.canvas.parentNode; this.w = this.container.offsetWidth; this.h = this.container.offsetHeight; this.wdpi = this.w * this.dpr; this.hdpi = this.h * this.dpr; this.canvas.width = this.wdpi; this.canvas.height = this.hdpi; this.canvas.style.width = this.w + "px"; this.canvas.style.height = this.h + "px"; this.ctx.scale(this.dpr, this.dpr); }; drawBubbleCanvas.prototype.animate = function () { let t = this; t.ctx.clearRect(0, 0, t.canvas.clientWidth, t.canvas.clientHeight); t.bubblesList.forEach(function (e) { e.update(); t.ctx.translate(e.translateX, e.translateY); t.ctx.beginPath(); t.ctx.arc(e.posX, e.posY, e.size, 0, 2 * Math.PI); t.ctx.fillStyle = "rgba(" + e.color + "," + e.alpha + ")"; t.ctx.fill(); t.ctx.setTransform(t.dpr, 0, 0, t.dpr, 0, 0); }); requestAnimationFrame(this.animate.bind(this)); }; drawBubbleCanvas.prototype.addBubble = function (t) { return this.bubblesList.push(t); }; drawBubbleCanvas.prototype.generateBubbles = function () { let t = this; for (let e = 0; e < t.bubbleDensity; e++) t.addBubble(new bubbleCanvas(t.canvas.parentNode)); }; // Night sky with stars canvas let starCanvas = function (t) { this.canvas = document.getElementById(t); this.ctx = this.canvas.getContext("2d"); this.dpr = window.devicePixelRatio; }; starCanvas.prototype.start = function () { let w; let h; const setCanvasExtents = () => { w = this.canvas.parentNode.clientWidth; h = this.canvas.parentNode.clientHeight; this.canvas.width = w; this.canvas.height = h; }; setCanvasExtents(); window.onresize = () => { setCanvasExtents(); }; const makeStars = (count) => { const out = []; for (let i = 0; i < count; i++) { const s = { x: Math.random() * w - w / 2, y: Math.random() * h - h / 2, z: Math.random() * 1000, }; out.push(s); } return out; }; let stars = makeStars(10000); const clear = () => { this.ctx.fillStyle = "#212121"; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); }; const putPixel = (x, y, brightness) => { const intensity = brightness * 255; const rgb = "rgb(" + intensity + "," + intensity + "," + intensity + ")"; this.ctx.beginPath(); this.ctx.arc(x, y, 0.9, 0, 2 * Math.PI); this.ctx.fillStyle = rgb; this.ctx.fill(); }; const moveStars = (distance) => { const count = stars.length; for (var i = 0; i < count; i++) { const s = stars[i]; s.z -= distance; while (s.z <= 1) { s.z += 1000; } } }; let prevTime; const init = (time) => { prevTime = time; requestAnimationFrame(tick); }; const tick = (time) => { let elapsed = time - prevTime; prevTime = time; moveStars(elapsed * 0.1); clear(); const cx = w / 2; const cy = h / 2; const count = stars.length; for (var i = 0; i < count; i++) { const star = stars[i]; const x = cx + star.x / (star.z * 0.001); const y = cy + star.y / (star.z * 0.001); if (x < 0 || x >= w || y < 0 || y >= h) { continue; } const d = star.z / 1000.0; const b = 1 - d * d; putPixel(x, y, b); } requestAnimationFrame(tick); }; requestAnimationFrame(init); }; // Start canvas animations window.addEventListener("load", function () { // Stars const headCanvas = new starCanvas("hero-particles"); // Bubbles const footerCanvas = new drawBubbleCanvas("footer-particles"); const mainCanvas = new drawBubbleCanvas("main-particles"); headCanvas.start(); footerCanvas.start(30); mainCanvas.start(200); });