updated feature

master
vitrinekast 6 months ago
parent ebc1ab7fc5
commit 9311e773fe

File diff suppressed because it is too large Load Diff

@ -11,15 +11,15 @@ $dataset = file_get_contents('exiftool.json');
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<title>Granularchive</title>
<link rel="stylesheet" href="/styles.css">
<link rel="stylesheet" href="styles.css">
</head>
@ -33,6 +33,7 @@ $dataset = file_get_contents('exiftool.json');
<h2 class='fn-title'></h2>
<iframe src="" frameborder="0"></iframe>
</aside>
<main>
<div id="container"></div>

@ -1,5 +1,7 @@
// Create some global variables
var width, height, audioEl, textEl;
var width, height, audioEl, textEl, sampEl;
var mouseOverId;
var tooltip;
let currentTransform;
var links = [],
nodes = [],
@ -9,7 +11,45 @@ let lastK = 0;
let svg;
var zoom;
let simulation;
const ROOT = "https://hub.xpub.nl/chopchop/archive_non-tree/";
const ROOT = "https://hub.xpub.nl/chopchop/archive_non-tree/Active-Archive";
function getNameFromPath(path) {
return path.split("/")[path.split("/").length - 1];
}
function wrap(text, width) {
text.each(function () {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.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", x)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
}
function parseExifData(files) {
// loop trough all files in JSON and add each to the list of nodes
@ -33,6 +73,7 @@ function parseExifData(files) {
nodes.push({
id: path,
FileType: "directory",
FileName: getNameFromPath(path),
});
}
});
@ -76,7 +117,11 @@ function parseExifData(files) {
function createGraph() {
// Create a scale to set the radius based on a file size (0 to 3 GB)
var rScale = d3.scaleLinear().domain([0, 30000000]).range([2, 15]);
var max = d3.max(nodes, function (d) {
return +d.FileSize;
});
console.log(max);
var rScale = d3.scaleLinear().domain([3, max]).range([2, 40]);
currentTransform = [width / 2, height / 2, height];
simulation = d3
@ -84,21 +129,18 @@ function createGraph() {
.force("center", d3.forceCenter(width / 2, height / 2))
.force(
"collision",
d3
.forceCollide()
// .radius((d) => rScale(d.size) + 1)
.iterations(3)
d3.forceCollide().radius((d) => rScale(d.FileSize) + 2)
)
.force(
"link",
d3
.forceLink(links)
.id((d) => d.id)
.strength((d) => 0.2)
// .distance((d) => (d.source.type === "directory" ? 80 : 20))
.strength((d) => 0.82)
.distance((d) => (d.source.FileType === "directory" ? 80 : 20))
)
.force("charge", d3.forceManyBody().strength(-1));
// .force("charge", d3.forceManyBody().strength(-1))
.force("charge", d3.forceManyBody());
// .alphaTarget(0.3); // stay hot
svg = d3
@ -108,15 +150,7 @@ function createGraph() {
const g = svg.append("g");
const labels = g
.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("font-size", (d) => (d.type === "directory" ? 12 : 3))
.text((d) => d.id)
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
tooltip = d3.select("body").append("div").attr("class", "tooltip");
const link = g
.append("g") //
@ -134,8 +168,7 @@ function createGraph() {
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", (d) => rScale(d.size))
.attr("r", 3)
.attr("r", (d) => rScale(d.FileSize))
.attr("stroke", "black")
.attr("fill", (d) => {
if (d.FileType === "directory") {
@ -148,12 +181,58 @@ function createGraph() {
return "white";
}
})
// .attr("fill","rgba(255,255,255,.5)")
.attr("label", (d) => d.id)
.attr("path", (d) => d.id)
.attr("file-type", (d) => d.FileType)
.attr("group", (d) => d.group);
.attr("group", (d) => d.group)
.on("mouseenter", function (e, d) {
// if (d3.select(this).attr("fill") !== "black") {
// d3.select(this).attr("fill", "grey");
// }
tooltip.style("display", "block").html(tooltipContents(d));
})
.on("click", function () {
// d3.selectAll("circle").attr("fill", "rgba(255,255,255,.5)");
// d3.select(this).attr("fill", "black");
var path = this.getAttribute("path");
svg
.transition() //
.duration(300)
.ease(d3.easeCubic)
.call(zoom.translateTo, this.getAttribute("cx"), this.getAttribute("cy"));
// do things based on the file type
if (path.match(/\.(?:wav|mp3|flac)$/i)) {
playAudio(path);
}
if (path.match(/\.(?:txt|png)$/i)) {
playText(path);
}
})
.on("mouseleave", function () {
if (d3.select(this).attr("fill") !== "black") {
d3.select(this).attr("fill", "rgba(255,255,255,.5)");
}
tooltip.style("display", "none");
})
.on("mousemove", function (event, d) {
if (!event) return;
tooltip.style("transform", `translate(${event.clientX}px, ${event.clientY}px)`);
});
const labels = g
.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("font-size", (d) => (d.FileType === "directory" ? 15 : 3))
.text((d) => d.FileName.replaceAll("-", " "))
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y)
.call(wrap, 50);
// Add a drag behavior.
node.call(
d3
@ -173,6 +252,7 @@ function createGraph() {
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
labels.attr("x", (d) => d.x).attr("y", (d) => d.y);
// tooltip.attr("x", (d) => d.x).attr("y", (d) => d.y);
});
// add zoom behavior
@ -183,41 +263,9 @@ function createGraph() {
[width, height],
])
.scaleExtent([1, 100])
.on("zoom", zoomed);
.on("zoom", onZoom);
svg.call(zoom);
// add some mouse behaviors
svg
.selectAll("circle")
.on("mouseenter", function (e) {
if (d3.select(this).attr("fill") !== "black") {
d3.select(this).attr("fill", "grey");
}
})
.on("click", function () {
d3.selectAll("circle").attr("fill", "rgba(255,255,255,.5)");
d3.select(this).attr("fill", "black");
var path = this.getAttribute("path");
svg
.transition() //
.duration(300)
.ease(d3.easeCubic)
.call(zoom.translateTo, this.getAttribute("cx"), this.getAttribute("cy"));
// do things based on the file type
if (path.match(/\.(?:wav|mp3|flac)$/i)) {
playAudio(path);
}
if (path.match(/\.(?:txt|png)$/i)) {
playText(path);
}
})
.on("mouseleave", function () {
if (d3.select(this).attr("fill") !== "black") {
d3.select(this).attr("fill", "rgba(255,255,255,.5)");
}
});
container.append(svg.node());
@ -242,22 +290,31 @@ function createGraph() {
event.subject.fy = null;
}
function zoomed(e) {
function onZoom(e) {
if (e.transform.k > 2 && lastK != e.transform.k) {
lastK = e.transform.k;
console.log("zoomed");
zoomLvl = Math.log2(e.transform.k);
globalNode.attr("stroke-width", 1 / zoomLvl);
link.attr("stroke-width", 1 / zoomLvl);
labels.attr("font-size", (d) => (d.type === "directory" ? 12 : 3) / zoomLvl);
labels.attr("font-size", (d) => (d.FileType === "directory" ? 20 : 3) / zoomLvl);
tooltip.attr("font-size", 3 / zoomLvl);
}
g.attr("transform", e.transform);
}
}
function tooltipContents(d) {
var string = "<ul>";
for (var prop in d) {
string += `<li><b>${prop}</b>: ${d[prop]}</li>`;
}
string += "</ul>";
return string;
}
function playAudio(src) {
audioEl.src = src;
audioEl.src = ROOT + "/" + src;
audioEl.currentTime = 0;
audioEl.play();
}
@ -292,17 +349,10 @@ window.onload = function () {
audioEl = document.querySelector(".fn-audio");
textEl = document.querySelector(".fn-text");
sampEl = document.querySelector("samp");
parseExifData(dataset);
createGraph();
var filetypes = [];
nodes.forEach((node) => {
if (filetypes.indexOf(node.FileType) == -1) {
filetypes.push(node.FileType);
}
});
console.log(filetypes);
// clear loading screen
document.querySelector(".loading").style.display = "none";

@ -16,4 +16,4 @@ tree -l -f --info --filelimit=500 -p -u -D -s -J -o tree.json
# OR exiftool
exiftool -json -r . > exiftool.json
exiftool -json -n -r . > exiftool.json

@ -12,7 +12,7 @@ body {
footer,
header,
aside {
aside, .tooltip {
position: fixed;
bottom: .5rem;
left: .5rem;
@ -75,4 +75,21 @@ circle {
display: flex;
justify-content: center;
align-items: center;
}
.tooltip {
position: fixed;
top: 0;
left: 0;
z-index: 2;
width: 300px;
display: none;
pointer-events: none;
bottom: auto;
right: auto;
}
.tooltip ul {
padding: 0 0;
list-style-type: none;
}
Loading…
Cancel
Save