Skip to content

Instantly share code, notes, and snippets.

@hyponymous
Forked from mbostock/.block
Last active October 7, 2015 04:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyponymous/425e419cb52c415a6427 to your computer and use it in GitHub Desktop.
Save hyponymous/425e419cb52c415a6427 to your computer and use it in GitHub Desktop.
Letter Scrambles
<!DOCTYPE html>
<link href="http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700" rel="stylesheet" type="text/css">
<meta charset="utf-8">
<style>
text {
font-family: 'Anonymous Pro', monospace;
font-size: 32px;
font-weight: bold;
color: rgb(51, 51, 51);
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script type="text/javascript">
function ScramblerView(el) {
this.letterWidth = 17;
this.lineHeight = 45;
this.lettersPerLine = 34;
var width = this.letterWidth * (this.lettersPerLine + 2),
height = 4 * this.lineHeight;
this.svg = d3.select(el).append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + this.letterWidth + ',' + this.lineHeight + ')');
}
ScramblerView.prototype.render = function(model) {
var data = model.text.split('').map(function (letter, index) {
return {
l: letter,
i: index
};
});
switch (model.mode) {
case 'full':
data = d3.shuffle(data);
break;
case 'word':
// only shuffle inside of words
var wordData = model.text.split(' ').map(function (word) {
return [word, 0];
});
// calculate the start indices
wordData.reduce(function (startIndex, wordDatum) {
wordDatum[1] = startIndex;
return startIndex + wordDatum[0].length + 1;
}, 0);
// shuffle within each pair of indices
wordData.map(function (wordDatum) {
return [wordDatum[1] + 1, wordDatum[1] + wordDatum[0].length - 1];
}).filter(function (indices) {
return indices[1] > indices[0];
}).forEach(function (indices) {
d3.shuffle(data, indices[0], indices[1]);
});
break;
case 'plain':
default:
break;
}
this.update(data);
};
ScramblerView.prototype.update = function(data) {
var letterWidth = this.letterWidth;
var lettersPerLine = this.lettersPerLine;
var lineHeight = this.lineHeight;
var rows = Math.floor(data.length / lettersPerLine);
this.svg
.transition()
.duration(500)
.attr('transform', 'translate(' + this.letterWidth + ',' + (2 - rows / 2) * this.lineHeight + ')');
function x(d, i) {
return letterWidth * (i % lettersPerLine);
}
function y(d, i) {
return lineHeight * Math.floor(i / lettersPerLine);
}
var text = this.svg.selectAll('text')
.data(data, function (d, i) { return d.l + '-' + d.i; });
text
.transition()
.duration(500)
.attr('x', x)
.attr('y', y);
text.enter()
.append('text')
.attr('dy', '.35em')
.attr('y', -5 * this.lineHeight)
.attr('x', x)
.style('fill-opacity', 1e-6)
.text(function (d) { return d.l; })
.transition()
.duration(500)
.attr('y', y)
.style('fill-opacity', 1);
text.exit()
.transition()
.duration(500)
.attr('y', 5 * this.lineHeight)
.style('fill-opacity', 1e-6)
.remove();
};
var scramblerView = new ScramblerView('body');
var scramblerModel = {
text: null,
mode: null,
};
// a simple state machine
var sentences = [
'It\'s a familiar trope that a written message may be intelligible even after some of its letters have been scrambled',
'Yet scrambling all the letters of a sentence renders it unreadable'
];
var transitions = {
full: 'word',
word: 'plain',
plain: 'full'
};
function step() {
// initialize / update
scramblerModel.mode = scramblerModel.mode || 'full';
if (scramblerModel.currentSentence == null) {
scramblerModel.currentSentence = 0;
}
scramblerModel.text = sentences[scramblerModel.currentSentence];
scramblerView.render(scramblerModel);
setTimeout(function () {
// transition
scramblerModel.mode = transitions[scramblerModel.mode] || scramblerModel.mode;
if (scramblerModel.mode === 'full') {
scramblerModel.currentSentence = (scramblerModel.currentSentence + 1) % sentences.length;
}
step();
}, 2500);
}
step();
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment