Skip to content

Instantly share code, notes, and snippets.

@jhellier
Last active June 30, 2020 22:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jhellier/6c3ef6c133e8116b4254 to your computer and use it in GitHub Desktop.
Save jhellier/6c3ef6c133e8116b4254 to your computer and use it in GitHub Desktop.
Finding Word Patterns

Built with blockbuilder.org

This was an experiment in visually identifying word patterns and then moving them out to form phrases.

"VISUALIZE PATTERNS IN YOUR DATA" is encoded for this message. Each letter of each word is placed at a specific location. When the code hits that location it highlights the letter and once the complete word has been found it copies the word to the message area below the scan area.

I used multiple layers of the letters to simulate identifying and then moving a target letter to another part of the screen while keeping the original letter in the original spot.

This kind of viz could be expanded on quite a bit to represent searching through bodies of text to visually identify key terms. A categorizer could be added to sort words into bins.

A better way to enter phrases would be a great addition.

Warning: This does not work properly in Safari. The target letters for the phrase should move down below the scan line, but they don't. They drop in at the beginning of the scan line. Not sure why.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg { width: 100%; height: 100%; }
</style>
</head>
<body>
<script>
var margin = {top: 120, right: 10, bottom: 20, left: 10};
var width = 960 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var letterGroupY = 0;
var overText;
var lastX = 100;
var letterSpacing = 15;
var argArray = [[1,5,9],[2,5,8],[3,5,2],[4,5,4],[5,5,4]];
var letters = "MVPIYDIANOASTZUTUTVRAAEKMALRWOPINSFAZSMPOEDFESWESQS";
var svgCircles = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right + 60)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.on("click", function() {
argArray = [[1,5,9],[2,5,8],[3,5,2],[4,5,4],[5,5,4]];
svgCircles.selectAll(".overTextLetter").remove();
lastX = 100;
findWords(argArray.shift());
})
var baseLetters = svgCircles.selectAll("baseLetters")
.data(letters)
.enter()
.append("text")
.attr("x", function(d,i) {
return 100 + (i * letterSpacing);
})
.attr("y", letterGroupY)
.style("opacity", 0.3)
.style("font","bold 28px monospace")
.text(function(d) { return d;});
function findWords(args) {
//Adds a layer that is identical to the bottom layer
//Allows the ability to move a ltter such that the bottom layer letter stays.
overText = svgCircles.selectAll(".overtext")
.data(letters)
.enter()
.append("text")
.classed("overTextLetter", true)
.attr("x", function(d,i) {
return 100 + (i * letterSpacing);
})
.attr("y", letterGroupY)
.style("opacity",0)
.style("font","bold 28px monospace")
.text(function(d,i) { return d;});
var letterPos = args[0],
cycle = args[1],
letterCount = args[2];
var count = 0;
var n = 0;
//Delay allows stepping through each one rather than doing all of them at the same time.
overText
.transition()
.delay(function(d,i) { return i * 30;})
.each(function(d,i) {
n++;
var currentPos = i;
if (count == letterCount) {
currentPos = -1;
}
var targetLetterPos = letterPos + (cycle * count);
if (currentPos == targetLetterPos) {
count++;
}
d3.select(this)
.transition()
.style("fill","green")
.style("opacity",1)
.transition()
.style("opacity",function(d) {
if (currentPos == targetLetterPos || d3.select(this).classed("moved")) {
return 1;
} else {
return 0;
}
})
.style("fill", function(d) {
if (currentPos == targetLetterPos || d3.select(this).classed("moved")) {
return "blue"
} else {
return "black";
}
});
})
.each("end", function(d,i) {
n--;
if (!n) {
moveWord();
}
});
};
findWords(argArray.shift());
function moveWord() {
var n = 0;
overText
.transition()
.duration(500)
.delay(500)
.attr("y", function(d,i) {
n++;
var color = d3.select(this).style("fill");
if (color == "rgb(0, 0, 255)" && !d3.select(this).classed("moved")) {
return letterGroupY + 30;
}
})
.attr("x", function(d,i) {
var color = d3.select(this).style("fill");
if (color == "rgb(0, 0, 255)" && !d3.select(this).classed("moved")) {
d3.select(this).classed("moved", true);
lastX = lastX + letterSpacing;
return lastX;
}
})
.each("end", function() {
n--;
if (!n) {
var args = argArray.shift();
if (args != undefined) {
lastX = lastX + letterSpacing;
findWords(args);
}
}
})
};
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment