In January 2021, Dr Egan worked with the Department of Digital Humanities and the Department of Music in UCC to create a web resource, www.ArtisticDoctorateResources.com which required a novel digital visualisation for a text-heavy website navigation. In order to achieve this, the Javascript library D3JS was used by implementing a version of a force layout. The existing D3 force layout uses a uses a “physics based simulator” which essentially means that there is a collision detection and gravitational force for each circle. On load the circles are pulled towards the centre, but on collide they repel each other and then take their place in the resultant gravity-collision negotiation!
A working example is available at the website, or on GitHub: rootseire.github.io/forceCluster
As a type of navigation menu, this visualisation needed to include a way of letting the visitor know which links they had visited on the site whenever they returned to the homepage. This was achieved by using Local Storage:
function checkStorage(){ var visited_links = JSON.parse(localStorage.getItem('visited_links')) || []; var links = document.querySelectorAll('a');<br>for (var i = 0; i < links.length; i++) {<br>var that = links[i];<br>var hrefs = that.href.baseVal;<br>var theElement = that; if (visited_links.indexOf(hrefs)!== -1) { theElement.classList.add("mystyle"); d3.selectAll('circle').on('click', datum => { console.log(datum.links); // the datum for the clicked circle<br>});</code>
Another function that was helpful for representing text within each circle was word-wrapping. In essence, when text becomes too wide for circles, this piece of code adds a new HTML element (tspan) for subsequent words:
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
The resultant visualisation code is available to other developers at: https://github.com/rootseire/forceCluster