monk
monk

Reputation: 4825

How to make matrix like text change effect in javascript?

I was trying to make this text change matrix movie like effect in JavaScript.The basic concept was that there is a div present in html and JavaScript take that div's inner text and manipulate it to create the continuously changing random text effect like in matrix movie. I am quite new to JavaScript, I am having hard time figuring out the logic behind the animation like the each steps, one step after another like what will happen next in whole animation process.

Anyways, I tried to make it on my own but as you can suspect i failed.

Here is my code :

<html>
<head>
    <script>

        var text = document.getElementById("text").innerText;
        var length_var = text.length;
        var possible = [];
        var possible_text ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var counter = 0;
        var arr_text = [];

        var new_func = function(){
            arr_text[Math.floor(Math.random() * length_var)] = possible.charAt(Math.floor(Math.random() * possible.length));
            alert(arr_text);

        };

        var call_func = function(){

            for(var i=0; i<=possible_text.length; i++){
                possible[i] = possible_text.charAt(i);
            }

            for(var i=0; i<= length_var ; i++){
                arr_text[i] = text.charAt(i);
            }

            setInterval(new_func, 100);

        };

    </script>
</head>
<body onload="call_func()">

    <div id="text">
        Hello There!
    </div>
</body>
</html>

What I was planning to do can be seen on this page, as I was highly motivated to do this effect on my own.

Link : http://events.ccc.de/congress/2012/wiki/Main_Page

The header text of the page contains such animation.

Please Help

Upvotes: 3

Views: 7708

Answers (6)

alexunn
alexunn

Reputation: 11

Elegant snippet

canvas = document.body.appendChild(document.createElement('canvas'))
screen = window.screen;
width = canvas.width = screen.width;
height = canvas.height = screen.height;
p = Array(255).join(1).split('');
context = canvas.getContext('2d');

setInterval(function(){
    context.fillStyle = 'rgba(0,0,0,0.05)';
    context.fillRect(0, 0, width, height);
    context.fillStyle = 'rgba(0,255,0,1)';
    p = p.map(function(v,i){
        r = Math.random();
        context.fillText(String.fromCharCode(Math.floor(2720 + r * 33)),i*10,v);
        v += 10; 
        return v > 768 + r * 1e4 ? 0 : v
    })
}, 33)

Upvotes: 1

Primoz Rome
Primoz Rome

Reputation: 11031

Here take a look at this JSFiddle, as put together from this resource. It is very fast and you can easily configure it.

Basically creates a blank canvas and renders the graphics. Here is the JS and HTML code that does that:

HTML:

<html style="background:black; width:100%; height:100%">
    <body style="background:black; width:100%; height:100%">
        <canvas id="c" style="display: block;"></canvas>
    </body>
</html>

JS:

var c = document.getElementById("c");
var ctx = c.getContext("2d");

//making the canvas full screen
c.height = window.innerHeight;
c.width = window.innerWidth;

//chinese characters - taken from the unicode charset
var chinese = "田由甲申甴电甶男甸甹町画甼甽甾甿畀畁畂畃畄畅畆畇畈畉畊畋界畍畎畏畐畑";
//converting the string into an array of single characters
chinese = chinese.split("");

var font_size = 10;
var columns = c.width/font_size; //number of columns for the rain
//an array of drops - one per column
var drops = [];
//x below is the x coordinate
//1 = y co-ordinate of the drop(same for every drop initially)
for(var x = 0; x < columns; x++)
    drops[x] = 1; 

//drawing the characters
function draw()
{
    //Black BG for the canvas
    //translucent BG to show trail
    ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
    ctx.fillRect(0, 0, c.width, c.height);

    ctx.fillStyle = "#0F0"; //green text
    ctx.font = font_size + "px arial";
    //looping over drops
    for(var i = 0; i < drops.length; i++)
    {
        //a random chinese character to print
        var text = chinese[Math.floor(Math.random()*chinese.length)];
        //x = i*font_size, y = value of drops[i]*font_size
        ctx.fillText(text, i*font_size, drops[i]*font_size);

        //sending the drop back to the top randomly after it has crossed the screen
        //adding a randomness to the reset to make the drops scattered on the Y axis
        if(drops[i]*font_size > c.height && Math.random() > 0.975)
            drops[i] = 0;

        //incrementing Y coordinate
        drops[i]++;
    }
}

setInterval(draw, 33);

Upvotes: 4

RobG
RobG

Reputation: 147453

If you want something that will randomise a string and slowly replace each character with the original, here's something that may suit. The replacement order is random too, so the string is replaced out of order but ends up with the original string.

A fancier solution is to give each letter its own timer with a different lag so they run at different speeds, and for different lengths of time. But that might suck some serious system resources for a big string.

function Randomiser(el, count, delay) {
  this.element = el;
  this.originalText = el.textContent || el.innerText || '';
  this.places = [];
  this.currentText = [];
  this.count = count || 3;   // iterations before fixing a character
  this.delay = delay || 100; // milliseconds between updates
  this.iteration = 0;
  this.startTime = new Date();

  var i = this.originalText.length;

  while (i--) {
    this.places[i] = [i];
  }
}

Randomiser.prototype.randomise = function() {
  var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  var i = this.places.length;

  while (i--) {
    this.currentText[this.places[i]] = charSet.charAt((Math.random() * charSet.length) | 0);
  }
  this.iteration += 1;
}

Randomiser.prototype.setContent = function() {
  var t = this.currentText.join('');

  if (typeof this.element.textContent == 'string') {
    this.element.textContent = t;
  } else {
    this.element.innerText = t;
  }
}

Randomiser.prototype.run = function() {
  var n;
  var temp = [];

  // If first run, randomise to initiate
  if (!this.iteration) {
    this.randomise();
  }

  // If there are places left
  if (this.places.length) {

    // If reached count, randomly remove one place and set its character
    // to the original value
    if (!(this.iteration % this.count)) {
      n = this.places.splice((Math.random() * this.places.length|0), 1)[0];
      this.currentText[n] = this.originalText.charAt(n);
    }

    // Randomise the string and call itself
    this.randomise(); 
    this.setContent();
    var randomiser = this;
    setTimeout(function(){randomiser.run();}, this.delay); 
  }
  // If no places left, end
}

// Kick it off
var r = new Randomiser(document.getElementById('text'), 5, 200);
r.run();

The above uses classic prototype inheritance, it could use a closure for the same thing. Also all those prototype functions could be put in a single object that is assigned to Randomiser.prototype.

Upvotes: 0

ShuklaSannidhya
ShuklaSannidhya

Reputation: 8976

Try this-

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript">
        function randString(len) {
            "use strict";
               var i, out="", all ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
                for (i = 0; i < len; i++) {
                    out += all.charAt(Math.floor(Math.random()*all.length));
                }
            return out;
        }
        function main() {
            "use strict";
            var $_inter = setInterval(function() {
                var text = document.getElementById("text");
                text.innerHTML = randString(text.innerHTML.length);
            }, 100);
        }
        window.onload = main;
        </script>
    </head>
    <body>
        <div id="text">Hello World!</div>
    </body>
</html>

Upvotes: 2

ShuklaSannidhya
ShuklaSannidhya

Reputation: 8976

This changes the string sequentially.

function main() {
    "use strict";
    var counter = 0, all = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var $_inter = setInterval(function() {
        var text = document.getElementById("text");
        text.innerHTML = text.innerHTML.substring(0, counter) + all.charAt(Math.floor(Math.random()*all.length)) + text.innerHTML.substring(counter+1);
        counter = (counter+1)%text.innerHTML.length;
    }, 100);
}
window.onload = main;

Upvotes: 2

LetterEh
LetterEh

Reputation: 26696

The crux of the program that's on the site (which is really, really ugly) involves creating an array of "haXX0r-like" characters, and then injecting them and removing them from the text.

They also speed up and slow down their process, and bounce between doing an addition pass and a removal pass, from what I saw on my quick read-through.

The downside of their code are that it's all a bunch of loops slopped together, with a bunch of "if"s to contain two or three loops, one after the other... ...and then they add "mode-switching" to that, where they say "if we're in mode-1 add stuff and do it quickly, and if we're in mode-2, remove stuff and lower the speed and if we're in this submode of either mode, set the speed accordingly, and if the speed is greater than this or less than that, and we're in this mode, then stop what we're doing, wait 5 seconds and call it again"...

...not pretty.

But they're starting with a quote, finding a random spot in the string, and then replacing the character at that spot with the character, plus the new "<", "?", "{", etc...

And speeding up and slowing down, as they add and remove the randomly-chosen character-type.

Upvotes: 1

Related Questions