Text that appears to "decode" as if the characters where encrypted.
4 states per letter: Transparent/Line/Block/Visible. These states are shuffled for a unique "decode" effect each time.
<div class="decode-text"> | |
<div class="text-animation">R</div> | |
<div class="text-animation">a</div> | |
<div class="text-animation">n</div> | |
<div class="text-animation">d</div> | |
<div class="text-animation">o</div> | |
<div class="text-animation">m</div> | |
<div class="text-animation">i</div> | |
<div class="text-animation">z</div> | |
<div class="text-animation">e</div> | |
<div class="text-animation">d</div> | |
<div class="space"></div> | |
<div class="text-animation">d</div> | |
<div class="text-animation">e</div> | |
<div class="text-animation">c</div> | |
<div class="text-animation">o</div> | |
<div class="text-animation">d</div> | |
<div class="text-animation">e</div> | |
<div class="space"></div> | |
<div class="text-animation">e</div> | |
<div class="text-animation">f</div> | |
<div class="text-animation">f</div> | |
<div class="text-animation">e</div> | |
<div class="text-animation">c</div> | |
<div class="text-animation">t</div> | |
</div> | |
<a id="refresh" onclick="decodeText();"> | |
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/><path d="M0 0h24v24H0z" fill="none"/></svg> | |
</a> |
/* ------------------------------------------------------------------------ * | |
4 states per letter: Transparent | Line | Block | Visible. | |
These states are shuffled for a unique "decode" effect each time. | |
* ------------------------------------------------------------------------ */ | |
function decodeText(){ | |
var text = document.getElementsByClassName('decode-text')[0]; | |
// debug with | |
// console.log(text, text.children.length); | |
// assign the placeholder array its places | |
var state = []; | |
for(var i = 0, j = text.children.length; i < j; i++ ){ | |
text.children[i].classList.remove('state-1','state-2','state-3'); | |
state[i] = i; | |
} | |
// shuffle the array to get new sequences each time | |
var shuffled = shuffle(state); | |
for(var i = 0, j = shuffled.length; i < j; i++ ){ | |
var child = text.children[shuffled[i]]; | |
classes = child.classList; | |
// fire the first one at random times | |
var state1Time = Math.round( Math.random() * (2000 - 300) ) + 50; | |
if(classes.contains('text-animation')){ | |
setTimeout(firstStages.bind(null, child), state1Time); | |
} | |
} | |
} | |
// send the node for later .state changes | |
function firstStages(child){ | |
if( child.classList.contains('state-2') ){ | |
child.classList.add('state-3'); | |
} else if( child.classList.contains('state-1') ){ | |
child.classList.add('state-2') | |
} else if( !child.classList.contains('state-1') ){ | |
child.classList.add('state-1'); | |
setTimeout(secondStages.bind(null, child), 100); | |
} | |
} | |
function secondStages(child){ | |
if( child.classList.contains('state-1') ){ | |
child.classList.add('state-2') | |
setTimeout(thirdStages.bind(null, child), 100); | |
} | |
else if( !child.classList.contains('state-1') ) | |
{ | |
child.classList.add('state-1') | |
} | |
} | |
function thirdStages(child){ | |
if( child.classList.contains('state-2') ){ | |
child.classList.add('state-3') | |
} | |
} | |
function shuffle(array) { | |
var currentIndex = array.length, temporaryValue, randomIndex; | |
// While there remain elements to shuffle... | |
while (0 !== currentIndex) { | |
// Pick a remaining element... | |
randomIndex = Math.floor(Math.random() * currentIndex); | |
currentIndex -= 1; | |
// And swap it with the current element. | |
temporaryValue = array[currentIndex]; | |
array[currentIndex] = array[randomIndex]; | |
array[randomIndex] = temporaryValue; | |
} | |
return array; | |
} | |
// Demo only stuff | |
decodeText(); | |
// beware: refresh button can overlap this timer and cause state mixups | |
setInterval(function(){ decodeText(); }, 10000); | |
.decode-text { | |
width: 100%; | |
font-size: 30px; | |
text-align: center; | |
} | |
.space { | |
display: inline-block; | |
width: 10px; | |
} | |
.text-animation { | |
display: inline-block; | |
position: relative; | |
color: transparent; | |
text-transform: uppercase; | |
&:before { | |
content: ""; | |
color: black; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
background: #0e182d; | |
width: 0; | |
height: 1.2em; | |
-webkit-transform: translate(-50%, -55%); | |
-ms-transform: translate(-50%, -55%); | |
transform: translate(-50%, -55%); | |
} | |
&.state-1 { | |
&:before { | |
width: 1px; | |
} | |
} | |
&.state-2 { | |
&:before { | |
width: 0.9em; | |
} | |
} | |
&.state-3 { | |
color: black; | |
&:before { | |
width: 0; | |
} | |
} | |
} | |
// demo styles | |
#refresh { | |
position: absolute; | |
top: 20px; | |
left: 20px; | |
cursor: pointer; | |
} | |
@import url(https://fonts.googleapis.com/css?family=Share+Tech+Mono); | |
div { | |
font-family: "Share Tech Mono", monospace; | |
} | |
body { | |
height: 100vh; | |
align-items: center; | |
display: flex; | |
} |