3
\$\begingroup\$

I would be glad if someone could take a look at my code and maybe improve it. It's an animation effect to gradually reveal text as if it were being decoded. I wouldn't mind if it could run with jQuery (if it's shorter or better). I uploaded it on jsbin.com. It's all about the effect and not about encryption or decryption.

I've written the following JS Code:

var got,
    chars,
    decrypted = document.getElementById("decoded"),
    encrypted = document.getElementById("encoded");
function change() {
    var randstring = "",
        rslength = chars.length - got.length,
        i;
    for (var x=0;x<rslength;x++) {
        i = Math.floor(Math.random() * chars.length);
        randstring += chars[i];
    }
    if (randstring[0] === chars[got.length]) {
        got += randstring[0];
        decrypted.textContent = got;
    } else {
        encrypted.textContent = randstring;
    }
    if (chars.length > got.length) {
        setTimeout(change, 10);
    } else {
        encrypted.textContent = "";
    }
}
function startdecrypt() {
    chars = decrypted.textContent;
    decrypted.textContent = "";
    got = "";
    setTimeout(change, 10);
}
if (window.addEventListener) {
    window.addEventListener('load', startdecrypt, false); //W3C
} else {
    window.attachEvent('onload', startdecrypt); //IE
}

And this short HTML part:

<span id="decoded">Enjoy this effect!</span>
<span id="encoded"></span>
\$\endgroup\$
5
\$\begingroup\$
var decrypted = document.getElementById("decoded");
var encrypted = document.getElementById("encoded");

function startdecrypt() {
    // Original text, split into an array and reversed (for faster pop())
    var originalText = decrypted.textContent.split('').reverse();
    var decryptedText = "";
    var i = 0;

    decrypted.textContent = "";

    var shuffleInterval = setInterval(function(){

      // Generate random strings. You can modify the generator function range
      // (Math.random()*(to-from+1)+from);
      var shuffledText = '';
      var j = originalText.length;
      while(j--) shuffledText += String.fromCharCode((Math.random()*94+33) | 0);
      // You can also use this generator to use only the remaining letters
      // while(j--) shuffledText += originalText[(Math.random()*j) | 0];

      // On every 10 cycles, remove a character from the original text to the decoded text
      if(i++ % 10 === 0) decryptedText += originalText.pop();

      // Display
      decrypted.textContent = decryptedText;
      encrypted.textContent = shuffledText;

      // Stop when done
      if(!shuffledText.length) clearInterval(shuffleInterval);

    // 50ms looks more dramatic
    },50);
}

if (window.addEventListener) {
    window.addEventListener('load', startdecrypt, false); //W3C
} else {
    window.attachEvent('onload', startdecrypt); //IE
}

Changes

  • Everything in one function

  • Simplified the code

  • Using setInterval rather than setTimeout. This is more efficient since you don't create timers everytime

  • More drama by adding random string generator, instead of just your original set of letters. This adds more mystery to the next letters.

  • In addition to the code, a monospace font would be more dramatic. It avoids the to-fro movement of the decoding text.

\$\endgroup\$
2
\$\begingroup\$

Joseph gave a fine answer, so this is just for fun. You said you might want a jQuery alternative, so here's a plugin. More code, but a lot more flexible.

Notable stuff: Options. You can control the number of time each letter should change before being "decoded", which letters should be used for the code, how long (roughly) the animation should run, and a class name for the span that holds the code.
The span that holds the code is created when the effect starts, and removed afterwards, so you only need the "real" text in the HTML.

Here's a demo and here's the plugin code

jQuery.fn.decodeEffect = (function ($) {
  var defaultOptions = {
    duration:      3000,
    stepsPerGlyph: 10,
    codeGlyphs:    "ABCDEFGHIJKLMNOPQRSTUWVXYZ1234567890",
    className:     "code"
  };

  // get a random string from the given set,
  // or from the 33 - 125 ASCII range
  function randomString(set, length) {
    var string = "", i, glyph;
    for(i = 0 ; i < length ; i++) {
      glyph = Math.random() * set.length;
      string += set[glyph | 0];
    }
    return string;
  }

  // this function starts the animation. Basically a closure
  // over the relevant vars. It creates a new separate span
  // for the code text, and a stepper function that performs
  // the animation itself
  function animate(element, options) {
    var text = element.text(),
    span = $("<span/>").addClass(options.className).insertAfter(element),
    interval = options.duration / (text.length * options.stepsPerGlyph),
    step = 0,
    length = 0,
    stepper = function () {
      if(++step % options.stepsPerGlyph === 0) {
        length++;
        element.text(text.slice(0, length));
      }
      if(length <= text.length) {
        span.text(randomString(options.codeGlyphs, text.length - length));
        setTimeout(stepper, interval);
      } else {
        span.remove();
      }
    };
    element.text("");
    stepper();
  }

  // Basic jQuery plugin pattern
  return function (options) {
    options = $.extend({}, defaultOptions, (options || {}));
    return this.each(function () {
      animate($(this), options);
    });
  };
}(jQuery));
\$\endgroup\$
  • \$\begingroup\$ This is also great Flambino‼ :) \$\endgroup\$ – Maximilian Fuchs Dec 20 '13 at 23:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.