chart = (libs, items) => {
const itemSize = 8;
const itemSpacing = itemSize * 0.25;
const layerSpaceing = itemSize * 0.125;
const layerSize = itemSize;
console.log("[chart] --", innerRadius(items.length, itemSize, itemSpacing));
const scale = canvasScale(
libs.length,
items.length,
itemSize,
itemSpacing,
layerSpaceing
);
console.log("[chart] - libs", libs.length);
const scaledWidth = width / scale;
const scaledHeigth = height / scale;
const r = (size) => size / 2;
const sectionHeight = (itemSize + layerSpaceing) * libs.length;
const sectionWidth = 2;
const radiusOffset =
sectionHeight + innerRadius(items.length, itemSize, itemSpacing);
const canvas = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [
-scaledWidth / 2,
-scaledHeigth / 2,
scaledWidth,
scaledHeigth
]);
// Images
const images = canvas
.append("g")
.attr("id", "images")
.selectAll("g")
.data(items);
const imagesEnter = images.enter().append("g");
// const imagesUpdate = images.merge();
// const imagesExit = images.exit();
imagesEnter
.attr("id", (d) => {
return d.id;
})
.attr("class", "image")
.on("click", (event, a) => console.log(a));
// .on("mouseover", (event, a) => console.log(a));
// .join(
// enter => enter.append("text")
// .attr("fill", "green")
// .attr("x", (d, i) => i * 16)
// .attr("y", -30)
// .text(d => d)
// .call(enter => enter.transition(t)
// .attr("y", 0)),
// update => update
// .attr("fill", "black")
// .attr("y", 0)
// .call(update => update.transition(t)
// .attr("x", (d, i) => i * 16)),
// exit => exit
// .attr("fill", "brown")
// .call(exit => exit.transition(t)
// .attr("y", 30)
// .remove())
// );
imagesEnter.append("g").attr("class", "label").attr("fill", "grey");
imagesEnter.append("g").attr("class", "files");
// Labeling Images
imagesEnter
.select(".label")
.append("text")
.text((d) => d.id)
.attr("text-anchor", (d, i) =>
angle(items.length, i) < 180 ? "start" : "end"
)
.attr("transform", (d, i) => {
if (angle(items.length, i) < 180) {
return `rotate(-90, 0, 0) translate(${itemSize + itemSpacing}, 6.5)`;
} else {
return `rotate(90, 0, 0) translate(${-itemSize - itemSpacing}, 4.5)`;
}
});
imagesEnter
.select(".label")
.append("circle")
.attr("r", r(itemSize))
.attr("cx", r(itemSize))
.attr("cy", -itemSpacing)
.style("fill", "none");
imagesEnter.attr(
"transform",
(d, i) => `
translate(0, ${0 - radiusOffset})
rotate(${angle(items.length, i)}, ${0}, ${radiusOffset} )
`
);
// Files
const fileTrans = canvas.transition().duration(750);
const delay = 50;
const fileUpdate = imagesEnter
.select(".files")
.selectAll("circle")
.data((d) => d.layers);
const fileEnter = fileUpdate
.enter()
.append("circle")
.attr("class", "file")
.attr("cx", 0)
.attr("cy", (d) => {
// const layer = layerOfFilteredLibrary(d.library_name || "__NONE__");
const layer = layerOfGroupLibraries(d.library_name || "__NONE__");
const offset = (itemSize + layerSpaceing) * layer;
return offset + r(itemSize);
})
.attr("r", 0)
.style("fill", (d) => {
return cameraModelStyling?.[d.camera_model_name]?.["fill"] || "red";
})
.attr("opacity", 0.4)
.call((update) =>
update
.transition(fileTrans)
.delay((d, i) => i * delay)
.attr("r", (d) => {
const image = items.find((element) => element.id == d.file_name);
const isSame = image.checksums.size == 1;
const scale = isSame ? 0.5 : 1;
return r(itemSize) * scale;
})
);
const fileExit = fileUpdate
.exit()
.call((exit) => exit.transition(fileTrans).attr("r", 0).remove());
// imagesExit.transition().duration(750).style("fill-opacity", 0).remove();
// fileEnter
// .attr("class", "file")
// .attr("cx", r(itemSize))
// .attr("cy", (d) => {
// const layer = layerOfFilteredLibrary(d.library_name || "__NONE__");
// const offset = (itemSize + layerSpaceing) * layer;
// return offset + r(itemSize);
// })
// .attr("r", (d) => {
// const image = items.find((element) => element.id == d.file_name);
// const isSame = image.checksums.size == 1;
// const scale = isSame ? 0.5 : 1;
// return r(itemSize) * scale;
// })
// .style("fill", (d) => {
// // if (!cameraModelStyling.hasOwnProperty(d.camera_model_name)) {
// // console.log(d);
// // }
// return cameraModelStyling?.[d.camera_model_name]?.["fill"] || "red";
// })
// .attr("stroke", (d) => {
// return cameraModelStyling?.[d.camera_model_name]?.["stroke"] || "black";
// })
// .attr("stroke-width", (d) => {
// return cameraModelStyling?.[d.camera_model_name]?.["stroke-width"] || 0;
// })
// .attr("opacity", 0.5);
// .attr("opacity", (d) => {
// const image = items.find((element) => element.id == d.file_name);
// const isSame = image.checksums.size == 1;
// return isSame ? 0.25 : 1;
// });
const guides = canvas.append("g").attr("id", "guides");
// Inner Guide ;)
const innerGuide = false;
if (innerGuide) {
guides
.append("circle")
.attr("id", "center")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", innerRadius(items.length, itemSize, itemSpacing))
.attr("stroke-width", 1)
.attr("stroke-opacity", 0.4)
.attr("stroke", "indianred")
.attr("fill", "none");
}
const layerGuide = false;
if (layerGuide) {
guides
.selectAll(".layerGuide")
.data(d3.range(0, libs.length))
.join("circle")
.attr("class", "layerGuide")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", (d) => {
const ir = innerRadius(items.length, itemSize, itemSpacing);
const f = (itemSize + layerSpaceing) * d;
return ir + f;
})
.style("fill", "none")
.style("stroke", "black")
.style("stroke-opacity", 0.1);
}
return canvas.node();
}