"animation panel"
Bootstrap 3.0.0 Snippet by evarevirus

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!DOCTYPE html><html lang='en' class=''> <head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/milesmanners/pen/MEwzMz" /> <style class="cp-pen-styles">@import url("https://fonts.googleapis.com/css?family=Open+Sans"); *, *::before, *::after { box-sizing: border-box; } html, body { width: 100%; height: 100%; } body { background: #1C1F2B; color: #fff; margin: 0px; font-family: 'Open Sans', sans-serif; } .container { display: flex; height: 100%; flex-direction: column; justify-content: center; padding: 20px; } .logo { position: relative; margin: auto; } .logo .mask, .logo canvas { display: block; width: inherit; height: inherit; } .logo .mask { position: absolute; top: -1px; left: -1px; text-indent: -9999px; box-sizing: content-box; } </style></head><body> <div class="container"> <div class="logo"></div> </div> <script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script> <script>/* jshint esversion: 6, asi: true, boss: true */ let $mm = Object.assign((s, attrs) => { if (s === null) return null let el if (s instanceof Element || s instanceof HTMLDocument || s instanceof Window) { el = s } else { let match = s.match(/<\/?(.*?)>/) el = match ? $mm.create(match[1], attrs) : $mm.find(s) } if (el === null) return null $mm.merge(el, $mm.fn) Object.defineProperty(el, 'val', { configurable: true, get: () => el.value, set: v => el.value = v }) Object.defineProperty(el, 'parent', { configurable: true, get: () => $mm(el.parentElement) }) Object.defineProperty(el, 'next', { configurable: true, get: () => $mm(el.nextElementSibling), set: v => el.appendAfter(v) }) Object.defineProperty(el, 'prev', { configurable: true, get: () => $mm(el.previousElementSibling), set: v => el.appendBefore(v) }) Object.defineProperty(el, 'bounds', { configurable: true, get: () => el.getBoundingClientRect() }) Object.defineProperty(el, 'text', { configurable: true, get: () => el.textContent, set: v => el.textContent = v }) Object.defineProperty(el, 'html', { configurable: true, get: () => el.innerHTML, set: v => el.innerHTML = v }) return el }, { find: s => $mm(document.querySelector(s)), findAll: s => [...document.querySelectorAll(s)].map(e => $mm(e)), create: (elName, attrs) => { let el = document.createElement(elName) if (attrs !== undefined) { let keys = Object.keys(attrs), styleKey = keys.find(k => k.toLowerCase() === 'style' && $mm.isObj(attrs[k])), innerHtmlKey = keys.find(k => k.toLowerCase() === 'innerhtml' || k.toLowerCase() === 'html') if (styleKey !== undefined) { for (let k in attrs[styleKey]) el.style[k] = attrs[styleKey][k] delete attrs[styleKey] } if (innerHtmlKey !== undefined) { el.innerHTML = attrs[innerHtmlKey] delete attrs[innerHtmlKey] } for (let k in attrs) el.setAttribute(k, attrs[k]) } return $mm(el) }, createSvg: (elName, attrs) => { let el = document.createElementNS('http://www.w3.org/2000/svg', elName) if (attrs !== undefined) { let keys = Object.keys(attrs), styleKey = keys.find(k => k.toLowerCase() === 'style' && $mm.isObj(attrs[k])), innerHtmlKey = keys.find(k => k.toLowerCase() === 'innerhtml' || k.toLowerCase() === 'html') if (styleKey !== undefined) { for (let k in attrs[styleKey]) el.style[k] = attrs[styleKey][k] delete attrs[styleKey] } if (innerHtmlKey !== undefined) { el.innerHTML = attrs[innerHtmlKey] delete attrs[innerHtmlKey] } for (let k in attrs) el.setAttribute(k, attrs[k]) } return $mm(el) }, rand: (max = 1, min = 0) => Math.random()*(max-min)+min, randInt: (max, min = 0) => ~~(Math.random()*(max-min)+min), randArr: arr => arr[$mm.randInt(arr.length)], isObj: obj => typeof obj === 'object' && obj.constructor !== RegExp && obj.constructor !== Date, merge: (deep, ...objs) => { if (deep !== true) return Object.assign(deep, ...objs) return objs.reduce((dest, src) => { if (Array.isArray(src)) return Array.isArray(dest) ? dest.concat(src) : src Object.keys(src).forEach(k => { if (src[k] && $mm.isObj(src[k])) $mm.merge(true, dest[k], src[k]) else dest[k] = src[k] }) return dest }) }, extend: (...objs) => { return $mm.merge($mm, ...objs) }, round: (num, prec = 2) => { let x = 10**prec return Math.round(num*x)/x }, dist: (p1, p2) => Math.hypot(p1.x - p2.x, p1.y - p2.y), cssVar: (v, val) => { if (val === undefined) return window.getComputedStyle(document.body).getPropertyValue(`--${v}`).trim() document.documentElement.style.setProperty(`--${v}`, val) }, array: (n, fn) => Array.from({length: n}, fn), fn: { find: function (s) { return $mm(this.querySelector(s)) }, findAll: function (s) { return [...this.querySelectorAll(s)].map(e => $mm(e)) }, on: function (type, ...args) { for (let t of type.split(' ')) this.addEventListener(t, ...args) return this }, appendBefore: function (el) { this.parent.insertBefore(el, this) return this }, appendAfter: function (el) { this.parent.insertBefore(el, this.nextSibling) return this }, appendTo: function (el) { el.append(this) return this }, addClass: function (c) { this.classList.add(c) return this }, removeClass: function (c) { this.classList.remove(c) return this }, toggleClass: function (c) { this.classList.toggle(c) return this }, hasClass: function (c) { return this.classList.contains(c) }, attr: function (a, val) { if (val === undefined) return this.getAttribute(a) this.setAttribute(a, val) return this }, data: function (a, val) { if (val === undefined) return this.getAttribute(`data-${a}`) this.setAttribute(`data-${a}`, val) return this }, getStyle: function (...attrs) { let style = window.getComputedStyle(this) let ret = {} if (attrs.length > 1) { for (let a of attrs) ret[a] = style.getPropertyValue(a) } else if (attrs.length == 1) { ret = style.getPropertyValue(attrs[0]) } else { for (let a in style) ret[a] = style.getPropertyValue(a) } return ret }, serialize: function () { let obj = {} this.findAll('input, select, textarea').forEach(field => { switch (field.type) { case 'checkbox': obj[field.name] = field.checked break case 'radio': if (field.checked) obj[field.name] = field.value else if (!(field.name in obj)) obj[field.name] = null break default: obj[field.name] = field.value } }) return obj }, validate: function () { let fields = this.findAll('[data-required]'), obj = {} fields.forEach(field => { switch (field.type) { case 'checkbox': break case 'radio': if (field.checked) obj[field.name] = true else if (!(field.name in obj)) obj[field.name] = false break default: obj[field.name] = field.value.length && field.validity.valid } }) let valid = Object.values(obj).every(e => e) if (!valid) fields.forEach(field => field.attr('required', '')) return $mm.merge({valid: valid}, obj) }, extend: (...objs) => { return $mm.merge($mm.fn, ...objs) } } })</script><script src='https://cdnjs.cloudflare.com/ajax/libs/granim/1.0.6/granim.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.5/dat.gui.min.js'></script><script src='https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js'></script> <script >/* jshint esversion: 6, asi: true, boss: true */ let loadedFonts = ['Serif'] let fonts = ['Acme', 'Anton', 'Arvo', 'Berkshire Swash', 'Dancing Script', 'Great Vibes', 'Indie Flower', 'Julius Sans One', 'Lobster', 'Open Sans', 'Oswald', 'Pacifico', 'Princess Sofia', 'Rock Salt', 'Serif', 'VT323', 'Yellowtail'] let opts = { fontSize: 128, font: $mm.randArr(fonts), text: 'Granim.js', bg: '#1C1F2B' } let el = $mm('.logo') let canvasEl = $mm('<canvas>').appendTo(el) let maskEl = $mm('<a>', { class: 'mask', href: 'javascript:window.location.href=window.location.href', html: opts.text, style: { border: `2px solid ${opts.bg}` } }).appendTo(el) CanvasRenderingContext2D.prototype.getTextHeight = function (text) { let body = $mm('body') let dummy = $mm('<div>', { style: { font: this.font } }) dummy.append(document.createTextNode(text)) body.append(dummy) let result = dummy.offsetHeight body.removeChild(dummy) return result } // Creates a mask canvas for the given parameters function textMask (text, fontSize, font, bg) { const canvas = $mm('<canvas>') const ctx = canvas.getContext('2d') // Looks complicated, but boils down to checking if the font is loaded // and loading it if it's not before creating the mask image return new Promise((resolve, reject) => { function createMask () { ctx.font = `${fontSize}px '${font}'` const metrics = ctx.measureText(text) const textWidth = metrics.width const textHeight = ctx.getTextHeight(text) canvas.attr('width', ~~(textWidth + textWidth / 10)) canvas.attr('height', ~~(textHeight + textHeight / 10)) ctx.textBaseline = 'hanging' ctx.font = `${fontSize}px ${font}` ctx.fillStyle = bg ctx.fillText(text, textWidth / 20, textHeight / 6) ctx.globalCompositeOperation = 'xor' ctx.fillRect(0, 0, canvas.width, canvas.height) resolve(canvas) } if (loadedFonts.includes(font)) { createMask() } else { WebFont.load({ google: { families: [font] }, active: () => { loadedFonts.push(font) createMask() } }) } }) } // Update the example function updateMask () { // Create the mask textMask(opts.text, opts.fontSize, opts.font, opts.bg).then(mask => { // Resize the container to fit the mask el.style.width = `${mask.attr('width')}px` el.style.height = `${mask.attr('height')}px` // Use the canvas as the background image maskEl.style.backgroundImage = `url(${mask.toDataURL()})` }) } // Run the example updateMask() // Initialize Granim new Granim({ element: canvasEl, direction: 'left-right', opacity: [1, 1], states : { 'default-state': { gradients: [ ['#EB3349', '#F45C43'], ['#FF8008', '#FFC837'], ['#4CB8C4', '#3CD3AD'], ['#24C6DC', '#514A9D'], ['#FF512F', '#DD2476'], ['#DA22FF', '#9733EE'] ], transitionSpeed: 2000 } } }) // Initialize Dat GUI let gui = new dat.GUI() gui.add(opts, 'text').onChange(updateMask) gui.add(opts, 'font', fonts).onChange(updateMask) gui.add(opts, 'fontSize', 12, 400).step(1).onChange(updateMask) //# sourceURL=pen.js </script> </body></html>

Related: See More


Questions / Comments: