Skip to content

Instantly share code, notes, and snippets.

@ideadapt
Created January 13, 2023 19:18
Show Gist options
  • Save ideadapt/e26649309fdb392b6d897aace635c5f7 to your computer and use it in GitHub Desktop.
Save ideadapt/e26649309fdb392b6d897aace635c5f7 to your computer and use it in GitHub Desktop.
Morph animation to blend / transform bit stream to characters using CSS, JavaScript and HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<style>
*,
*::before,
*::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: 'Courier New', monospace, serif;
}
.container {
height: 100vh;
width: 90vw;
min-width: 800px;
margin: 0 auto;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-content: center;
}
.container>div {
display: flex;
min-height: 100px;
}
.morphing {
position: relative;
overflow: hidden;
font-size: 80px;
background-color: #fff;
color: #000;
width: 57px;
filter: contrast(25) blur(1px);
}
@keyframes blend {
0%,
5%,
100% {
filter: blur(0px);
opacity: 1;
}
20%,
80% {
filter: blur(1em);
opacity: 0;
}
}
.morphing>div {
position: absolute;
/*0-2s visible (blur out), 2-8s inivisble, 8-10s visible (blur in)*/
animation: blend 10s 1 ease-in-out;
}
.morphing>div:first-child {
animation-play-state: paused;
animation-delay: 2s;
}
.morphing>div:last-child {
animation-play-state: paused;
animation-delay: -7s;
}
.morphing>div:first-child {
font-size: 50px;
padding-top: 25px;
}
</style>
<div class="container">
</div>
<script>
const binaryToText = (binary) => String.fromCharCode(parseInt(binary, 2))
// const textToBinary = (text) => text.split('').map(char => char.charCodeAt(0).toString(2).padStart(8, '0')).join('')
const bits = document.location.hash.substring(1).trim()
if (bits.length === 0) throw new Error("Missing bits in URL hash");
const container = document.getElementsByClassName('container')[0]
let charBits = ''
let word = document.createElement('div')
bits.split('').forEach(bit => {
charBits += bit
if (charBits.length == 8) {
const morph = document.createElement('div')
morph.className = 'morphing'
const bits = document.createElement('div')
bits.innerText = charBits
morph.appendChild(bits)
const char = document.createElement('div')
char.innerText = binaryToText(charBits)
if (char.innerText === ' ') {
word = document.createElement('div')
}
morph.appendChild(char)
word.appendChild(morph)
container.appendChild(word)
charBits = ''
}
})
let charIndex = 0
const morphs = [...document.querySelectorAll('.morphing')]
const morphCount = morphs.length
const cancelInterval = window.setInterval(() => {
charIndex++;
const morph = morphs[charIndex - 1]
const bits = morph.querySelector('div:first-child')
const char = morph.querySelector('div:last-child')
bits.style.animationPlayState = 'running'
char.style.animationPlayState = 'running'
window.setTimeout(() => bits.style.display = 'none', 9000)
if (charIndex >= morphCount) {
clearInterval(cancelInterval)
}
}, 150)
</script>
</body>
<!--
# usage
index.html#010001000110000101101110011010110110010100100000011001101111110001110010001000000110010001100101011010010110111001100101011011100010000001000101011010010110111001110011011000010111010001111010
# inspired by https://codepen.io/amit_sheen/pen/xxqYzvm
# tested on
macos monteray
ff latest-107
chrome latest-107
safari 15.1
no bits
opera latest
macos big sur
safari 14.1
no bits
edge latest
windows 11
chrome 107
opera 92
samsung
s22+ stock
s20 stock
google
pixel5 ff (laggy)
pixel5 chrome (laggy)
iphone
xs12,13 safari
11 safari
11,12,13,14 safari
-->
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment