Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created November 17, 2016 23:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CodeMyUI/798c4612f524c01a39fd67d6a8fdd060 to your computer and use it in GitHub Desktop.
Save CodeMyUI/798c4612f524c01a39fd67d6a8fdd060 to your computer and use it in GitHub Desktop.
Random Text Shuffle
<article>
<h1 id="headline">Random Text Shuffle</h1>
<p id="text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nostrum dignissimos sint dolores necessitatibus repellendus in nemo expedita ullam numquam, placeat, laborum beatae, vero. Similique dolorem enim repellat impedit reiciendis, non.</p>
<button id="shuffler">shuffle</button>
</article>
function WordShuffler(holder,opt){
var that = this;
var time = 0;
this.now;
this.then = Date.now();
this.delta;
this.currentTimeOffset = 0;
this.word = null;
this.currentWord = null;
this.currentCharacter = 0;
this.currentWordLength = 0;
var options = {
fps : 20,
timeOffset : 5,
textColor : '#000',
fontSize : "50px",
useCanvas : false,
mixCapital : false,
mixSpecialCharacters : false,
needUpdate : true,
colors : [
'#f44336','#e91e63','#9c27b0',
'#673ab7','#3f51b5','#2196f3',
'#03a9f4','#00bcd4','#009688',
'#4caf50','#8bc34a','#cddc39',
'#ffeb3b','#ffc107','#ff9800',
'#ff5722','#795548','#9e9e9e',
'#607d8b'
]
}
if(typeof opt != "undefined"){
for(key in opt){
options[key] = opt[key];
}
}
this.needUpdate = true;
this.fps = options.fps;
this.interval = 1000/this.fps;
this.timeOffset = options.timeOffset;
this.textColor = options.textColor;
this.fontSize = options.fontSize;
this.mixCapital = options.mixCapital;
this.mixSpecialCharacters = options.mixSpecialCharacters;
this.colors = options.colors;
this.useCanvas = options.useCanvas;
this.chars = [
'A','B','C','D',
'E','F','G','H',
'I','J','K','L',
'M','N','O','P',
'Q','R','S','T',
'U','V','W','X',
'Y','Z'
];
this.specialCharacters = [
'!','§','$','%',
'&','/','(',')',
'=','?','_','<',
'>','^','°','*',
'#','-',':',';','~'
]
if(this.mixSpecialCharacters){
this.chars = this.chars.concat(this.specialCharacters);
}
this.getRandomColor = function () {
var randNum = Math.floor( Math.random() * this.colors.length );
return this.colors[randNum];
}
//if Canvas
this.position = {
x : 0,
y : 50
}
//if DOM
if(typeof holder != "undefined"){
this.holder = holder;
}
if(!this.useCanvas && typeof this.holder == "undefined"){
console.warn('Holder must be defined in DOM Mode. Use Canvas or define Holder');
}
this.getRandCharacter = function(characterToReplace){
if(characterToReplace == " "){
return ' ';
}
var randNum = Math.floor(Math.random() * this.chars.length);
var lowChoice = -.5 + Math.random();
var picketCharacter = this.chars[randNum];
var choosen = picketCharacter.toLowerCase();
if(this.mixCapital){
choosen = lowChoice < 0 ? picketCharacter.toLowerCase() : picketCharacter;
}
return choosen;
}
this.writeWord = function(word){
this.word = word;
this.currentWord = word.split('');
this.currentWordLength = this.currentWord.length;
}
this.generateSingleCharacter = function (color,character) {
var span = document.createElement('span');
span.style.color = color;
span.innerHTML = character;
return span;
}
this.updateCharacter = function (time) {
this.now = Date.now();
this.delta = this.now - this.then;
if (this.delta > this.interval) {
this.currentTimeOffset++;
var word = [];
if(this.currentTimeOffset === this.timeOffset && this.currentCharacter !== this.currentWordLength){
this.currentCharacter++;
this.currentTimeOffset = 0;
}
for(var k=0;k<this.currentCharacter;k++){
word.push(this.currentWord[k]);
}
for(var i=0;i<this.currentWordLength - this.currentCharacter;i++){
word.push(this.getRandCharacter(this.currentWord[this.currentCharacter+i]));
}
if(that.useCanvas){
c.clearRect(0,0,stage.x * stage.dpr , stage.y * stage.dpr);
c.font = that.fontSize + " sans-serif";
var spacing = 0;
word.forEach(function (w,index) {
if(index > that.currentCharacter){
c.fillStyle = that.getRandomColor();
}else{
c.fillStyle = that.textColor;
}
c.fillText(w, that.position.x + spacing, that.position.y);
spacing += c.measureText(w).width;
});
}else{
if(that.currentCharacter === that.currentWordLength){
that.needUpdate = false;
}
this.holder.innerHTML = '';
word.forEach(function (w,index) {
var color = null
if(index > that.currentCharacter){
color = that.getRandomColor();
}else{
color = that.textColor;
}
that.holder.appendChild(that.generateSingleCharacter(color, w));
});
}
this.then = this.now - (this.delta % this.interval);
}
}
this.restart = function () {
this.currentCharacter = 0;
this.needUpdate = true;
}
function update(time) {
time++;
if(that.needUpdate){
that.updateCharacter(time);
}
requestAnimationFrame(update);
}
this.writeWord(this.holder.innerHTML);
console.log(this.currentWord);
update(time);
}
var headline = document.getElementById('headline');
var text = document.getElementById('text');
var shuffler = document.getElementById('shuffler');
var headText = new WordShuffler(headline,{
textColor : '#fff',
timeOffset : 18,
mixCapital : true,
mixSpecialCharacters : true
});
var pText = new WordShuffler(text,{
textColor : '#fff',
timeOffset : 2
});
var buttonText = new WordShuffler(shuffler,{
textColor : 'tomato',
timeOffset : 10
});
shuffler.addEventListener('click',function () {
headText.restart();
pText.restart();
buttonText.restart();
});
*{
box-sizing:border-box;
}
html,body{
width:100%;
height:100%;
}
body{
margin:0;
overflow:hidden;
background:#222;
font-family: monospace;
}
h1{
margin-top:0;
}
button{
font-family: monospace;
border:2px solid tomato;
background:transparent;
width:250px;
font-size:1.2em;
padding : 10px 0;
border-radius:5px;
display:block;
cursor:pointer;
margin:1em auto;
}
article{
width:80%;
margin:auto;
font-size:2em;
top:50%;
position:relative;
transform:translateY(-50%);
}
@HoRyanh
Copy link

HoRyanh commented Apr 7, 2017

Hi, thank you very much for sharing. I really love your work. I have use your js code on my homework, but I got a bug and I have no idea how to fix it. I just copy paste the function and the first time when I clicking on the button everything are just fine, but the text is changed when I click on the second time. Can you please help me to fix it? I had spend 3 hours to finding the bug. Thank you.
firstclick
secondclick

My js file. Sorry, I'm new, not yet to know how to upload the code.

function WordShuffler(holder,opt){
var that = this;
var time = 0;
this.now;
this.then = Date.now();

this.delta;
this.currentTimeOffset = 0;

this.word = null;
this.currentWord = null;
this.currentCharacter = 0;
this.currentWordLength = 0;


var options = {
    fps : 20,
    timeOffset : 5,
    textColor : '#000',
    fontSize : "50px",
    useCanvas : false,
    mixCapital : false,
    mixSpecialCharacters : false,
    needUpdate : true,
    colors : [
              '#f44336','#e91e63','#9c27b0',
              '#673ab7','#3f51b5','#2196f3',
              '#03a9f4','#00bcd4','#009688',
              '#4caf50','#8bc34a','#cddc39',
              '#ffeb3b','#ffc107','#ff9800',
              '#ff5722','#795548','#9e9e9e',
              '#607d8b'
              ]
}

if(typeof opt != "undefined"){
    for(key in opt){
        options[key] = opt[key];
    }
}



this.needUpdate = true;
this.fps = options.fps;
this.interval = 1000/this.fps;
this.timeOffset = options.timeOffset;
this.textColor = options.textColor;
this.fontSize = options.fontSize;
this.mixCapital = options.mixCapital;
this.mixSpecialCharacters = options.mixSpecialCharacters;
this.colors = options.colors;

this.useCanvas = options.useCanvas;

this.chars = [
              'A','B','C','D',
              'E','F','G','H',
              'I','J','K','L',
              'M','N','O','P',
              'Q','R','S','T',
              'U','V','W','X',
              'Y','Z'
              ];
this.specialCharacters = [
                          '!','§','$','%',
                          '&','/','(',')',
                          '=','?','_','<',
                          '>','^','°','*',
                          '#','-',':',';','~'
                          ]

if(this.mixSpecialCharacters){
    this.chars = this.chars.concat(this.specialCharacters);
}

this.getRandomColor = function () {
    var randNum = Math.floor( Math.random() * this.colors.length );
    return this.colors[randNum];
}

//if Canvas

this.position = {
    x : 0,
    y : 50
}

//if DOM
if(typeof holder != "undefined"){
    this.holder = holder;
}

if(!this.useCanvas && typeof this.holder == "undefined"){
    console.warn('Holder must be defined in DOM Mode. Use Canvas or define Holder');
}


this.getRandCharacter = function(characterToReplace){
    if(characterToReplace == " "){
        return ' ';
    }
    var randNum = Math.floor(Math.random() * this.chars.length);
    var lowChoice =  -.5 + Math.random();
    var picketCharacter = this.chars[randNum];
    var choosen = picketCharacter.toLowerCase();
    if(this.mixCapital){
        choosen = lowChoice < 0 ? picketCharacter.toLowerCase() : picketCharacter;
    }
    return choosen;
    
}

this.writeWord = function(word){
    this.word = word;
    this.currentWord = word.split('');
    this.currentWordLength = this.currentWord.length;
    
}

this.generateSingleCharacter = function (color,character) {
    var span = document.createElement('span');
    span.style.color = color;
    span.innerHTML = character;
    return span;
}

this.updateCharacter = function (time) {
    
    this.now = Date.now();
    this.delta = this.now - this.then;
    
    
    
    if (this.delta > this.interval) {
        this.currentTimeOffset++;
        
        var word = [];
        
        if(this.currentTimeOffset === this.timeOffset && this.currentCharacter !== this.currentWordLength){
            this.currentCharacter++;
            this.currentTimeOffset = 0;
        }
        for(var k=0;k<this.currentCharacter;k++){
            word.push(this.currentWord[k]);
        }
        
        for(var i=0;i<this.currentWordLength - this.currentCharacter;i++){
            word.push(this.getRandCharacter(this.currentWord[this.currentCharacter+i]));
        }
        
        
        if(that.useCanvas){
            c.clearRect(0,0,stage.x * stage.dpr , stage.y * stage.dpr);
            c.font = that.fontSize + " sans-serif";
            var spacing = 0;
            word.forEach(function (w,index) {
                         if(index > that.currentCharacter){
                         c.fillStyle = that.getRandomColor();
                         }else{
                         c.fillStyle = that.textColor;
                         }
                         c.fillText(w, that.position.x + spacing, that.position.y);
                         spacing += c.measureText(w).width;
                         });
        }else{
            
            if(that.currentCharacter === that.currentWordLength){
                that.needUpdate = false;
            }
            this.holder.innerHTML = '';
            word.forEach(function (w,index) {
                         var color = null
                         if(index > that.currentCharacter){
                         color = that.getRandomColor();
                         }else{
                         color = that.textColor;
                         }
                         that.holder.appendChild(that.generateSingleCharacter(color, w));
                         }); 
        }
        this.then = this.now - (this.delta % this.interval);
    }
}

this.restart = function () {
    this.currentCharacter = 0;
    this.needUpdate = true;
}

function update(time) {
    time++;
    if(that.needUpdate){
        that.updateCharacter(time);
    }
    requestAnimationFrame(update);
}

this.writeWord(this.holder.innerHTML);


console.log(this.currentWord);
update(time);

}

function getID(thisID){
var modal, text, pText;
if(thisID == "contactBtn"){
modal = document.getElementById("contact");
modal.style.display = "block";
text = document.getElementById("email");
pText = new WordShuffler(text,{
textColor : '#fff',
timeOffset : 2,
mixCapital : true,
mixSpecialCharacters : true
});

}
else if(thisID == "aboutBtn"){
    
}
else if(thisID == "resumeBtn"){
    
}

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks on <span> (x), close the modal
span.onclick = function() {
    modal.style.display = "none";
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
    if (event.target == modal) {
        modal.style.display = "none";
    }
}

}

@avinashpatel123
Copy link

avinashpatel123 commented Feb 17, 2018

Hello, I copied the js and added the effect for <a> tag and gave an condition to run onclick().
Here in my html code there are a list of <a> tag and I want to add same effect to each <a> tag when it is clicked and till now everything was doing fine,
But problem is the affect is applied only to the first <a> tag and for second <a> tag when clicked console log gives the warning "Holder must be defined in DOM Mode. Use Canvas or define Holder" with an error "Cannot read property 'innerHTML' of undefined"

Someone please help me out from this situation.
Thanks in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment