From 0c5b9c8d20e2bfd0a45818b0312e725ca05a974d Mon Sep 17 00:00:00 2001 From: niclas Date: Wed, 28 Feb 2024 13:10:51 +0100 Subject: [PATCH 1/6] Add [graph] legend --- .../docs/01_attachements/javascripts/graph.js | 108 ++++++++++++++++-- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index ced8070..0fb97a8 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -1,7 +1,7 @@ document$.subscribe(function () { const NODE_RADIUS = 8; - const NODE_COLOR = "#69b3a2"; + // const NODE_COLOR = "#69b3a2"; const Parent_Node_COLOR = "#ff0000"; @@ -55,7 +55,8 @@ document$.subscribe(function () { var newNodes = Array.from(new Set(newData.flatMap(d => [d.source, d.target]))) .map(id => ({ id, - path: nodePaths[id] + path: nodePaths[id], + galaxy: newData.find(d => d.source === id) ? newData.find(d => d.source === id).sourceGalaxy : newData.find(d => d.target === id).targetGalaxy })); var newLinks = newData.map(d => ({ source: d.source, target: d.target })); @@ -76,10 +77,18 @@ document$.subscribe(function () { nodePaths[d.target] = d.targetPath || null; }); + // Extract unique galaxy names from data + const galaxies = Array.from(new Set(data.flatMap(d => [d.sourceGalaxy, d.targetGalaxy]))); + + // Create a color scale using D3's scaleOrdinal and a color scheme + const colorScale = d3.scaleOrdinal(d3.schemeTableau10) + .domain(galaxies); // Maps galaxy names to colors in the scheme + var nodes = Array.from(new Set(data.flatMap(d => [d.source, d.target]))) .map(id => ({ id, - path: nodePaths[id] + path: nodePaths[id], + galaxy: data.find(d => d.source === id) ? data.find(d => d.source === id).sourceGalaxy : data.find(d => d.target === id).targetGalaxy })); const Parent_Node = nodes[0]; @@ -102,7 +111,7 @@ document$.subscribe(function () { var simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).id(d => d.id).distance(linkDistance)) - .force("charge", d3.forceManyBody().strength(-50)) + .force("charge", d3.forceManyBody().strength(-30)) .force("center", d3.forceCenter(width / 2, height / 2)) .alphaDecay(0.02); // A lower value, adjust as needed @@ -126,8 +135,9 @@ document$.subscribe(function () { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }) .attr("fill", function (d, i) { - return d.id === Parent_Node.id ? Parent_Node_COLOR : NODE_COLOR; - }); + return d.id === Parent_Node.id ? Parent_Node_COLOR : colorScale(d.galaxy); + }) + .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-')); // Apply tooltip on nodes node.on("mouseover", function (event, d) { @@ -178,6 +188,87 @@ document$.subscribe(function () { if (!event.active) simulation.alphaTarget(0); } + // Prepare legend data + const legendData = galaxies.map(galaxy => ({ + name: galaxy, + color: colorScale(galaxy) + })); + + const maxCharLength = 10; // Maximum number of characters to display in legend + // Create legend + const legend = svg.append("g") + .attr("class", "legend") + .attr("transform", "translate(" + (width - 100) + ",20)"); // Adjust position as needed + + // Add legend title + legend.append("text") + .attr("x", 0) + .attr("y", -10) + .style("font-size", "13px") + .style("text-anchor", "start") + .style("fill", "grey") + .text("Galaxy Colors"); + + // Add colored rectangles and text labels for each galaxy + const legendItem = legend.selectAll(".legend-item") + .data(legendData) + .enter().append("g") + .attr("class", "legend-item") + .attr("transform", (d, i) => `translate(0, ${i * 20})`); + + legendItem.append("rect") + .attr("width", 12) + .attr("height", 12) + .style("fill", d => d.color) + .on("mouseover", function (event, d) { + // Highlight all nodes associated with this galaxy + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) + .attr("r", NODE_RADIUS + 5); + tooltip.transition() + .duration(200) + .style("opacity", .9); + tooltip.html(d.name) + .style("left", (event.pageX) + "px") + .style("top", (event.pageY - 28) + "px"); + }) + .on("mouseout", function (event, d) { + // Remove highlight from all nodes + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) + .attr("r", NODE_RADIUS); + tooltip.transition() + .duration(500) + .style("opacity", 0); + }); + + legendItem.append("text") + .attr("x", 24) + .attr("y", 9) + .attr("dy", "0.35em") + .style("text-anchor", "start") + .style("fill", "grey") + .style("font-size", "12px") + // .text(d => d.name); + .text(d => d.name.length > maxCharLength ? d.name.substring(0, maxCharLength) + "..." : d.name) + .on("mouseover", function (event, d) { + // Repeat the highlight effect here for consistency + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) + .attr("r", NODE_RADIUS + 5); + tooltip.transition() + .duration(200) + .style("opacity", .9); + tooltip.html(d.name) + .style("left", (event.pageX) + "px") + .style("top", (event.pageY - 28) + "px"); + }) + .on("mouseout", function (event, d) { + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) + .attr("r", NODE_RADIUS); + tooltip.transition() + .duration(500) + .style("opacity", 0); + }); + + // Update positions on each simulation 'tick' simulation.on("tick", () => { nodes.forEach(d => { @@ -208,8 +299,9 @@ document$.subscribe(function () { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }) .attr("fill", function (d, i) { - return d.id === Parent_Node.id ? Parent_Node_COLOR : NODE_COLOR; - }), + return d.id === Parent_Node.id ? Parent_Node_COLOR : colorScale(d.galaxy); + }) + .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-')), update => update, exit => exit.remove() ); From d4df918d7741c8b283a731bf5928529518cdca38 Mon Sep 17 00:00:00 2001 From: niclas Date: Wed, 28 Feb 2024 13:54:38 +0100 Subject: [PATCH 2/6] Fix [graph] replace . from galaxy class names --- .../docs/01_attachements/javascripts/graph.js | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index 0fb97a8..0add079 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -137,7 +137,7 @@ document$.subscribe(function () { .attr("fill", function (d, i) { return d.id === Parent_Node.id ? Parent_Node_COLOR : colorScale(d.galaxy); }) - .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-')); + .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')); // Apply tooltip on nodes node.on("mouseover", function (event, d) { @@ -216,13 +216,13 @@ document$.subscribe(function () { .attr("class", "legend-item") .attr("transform", (d, i) => `translate(0, ${i * 20})`); - legendItem.append("rect") + legendItem.append("rect") // change node radius info TODO .attr("width", 12) .attr("height", 12) .style("fill", d => d.color) .on("mouseover", function (event, d) { // Highlight all nodes associated with this galaxy - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .attr("r", NODE_RADIUS + 5); tooltip.transition() .duration(200) @@ -233,8 +233,10 @@ document$.subscribe(function () { }) .on("mouseout", function (event, d) { // Remove highlight from all nodes - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) - .attr("r", NODE_RADIUS); + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .attr("r", function (d, i) { + return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; + }); tooltip.transition() .duration(500) .style("opacity", 0); @@ -251,8 +253,13 @@ document$.subscribe(function () { .text(d => d.name.length > maxCharLength ? d.name.substring(0, maxCharLength) + "..." : d.name) .on("mouseover", function (event, d) { // Repeat the highlight effect here for consistency - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) - .attr("r", NODE_RADIUS + 5); + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + // .attr("r", NODE_RADIUS + 5); + .each(function () { + // 'this' refers to the individual SVG circle elements + var currentRadius = d3.select(this).attr("r"); + d3.select(this).attr("r", parseFloat(currentRadius) + 5); + }); tooltip.transition() .duration(200) .style("opacity", .9); @@ -261,8 +268,10 @@ document$.subscribe(function () { .style("top", (event.pageY - 28) + "px"); }) .on("mouseout", function (event, d) { - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-')) - .attr("r", NODE_RADIUS); + svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .attr("r", function (d, i) { + return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; + }); tooltip.transition() .duration(500) .style("opacity", 0); @@ -301,7 +310,7 @@ document$.subscribe(function () { .attr("fill", function (d, i) { return d.id === Parent_Node.id ? Parent_Node_COLOR : colorScale(d.galaxy); }) - .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-')), + .attr("class", d => "node galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')), update => update, exit => exit.remove() ); From 9bc289a4b11ffb0c7099eb6e1877e677b1def9f7 Mon Sep 17 00:00:00 2001 From: niclas Date: Wed, 28 Feb 2024 14:05:28 +0100 Subject: [PATCH 3/6] Add [graph] node enlargement while hovering --- .../docs/01_attachements/javascripts/graph.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index 0add079..a65d8e1 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -147,6 +147,7 @@ document$.subscribe(function () { tooltip.html(d.id) .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); + d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") @@ -156,6 +157,9 @@ document$.subscribe(function () { tooltip.transition() .duration(500) .style("opacity", 0); + d3.select(this).attr("r", function (d, i) { + return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; + }); }); // Apply links on nodes @@ -223,7 +227,10 @@ document$.subscribe(function () { .on("mouseover", function (event, d) { // Highlight all nodes associated with this galaxy svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) - .attr("r", NODE_RADIUS + 5); + .each(function () { + var currentRadius = d3.select(this).attr("r"); + d3.select(this).attr("r", parseFloat(currentRadius) + 5); + }); tooltip.transition() .duration(200) .style("opacity", .9); @@ -252,11 +259,8 @@ document$.subscribe(function () { // .text(d => d.name); .text(d => d.name.length > maxCharLength ? d.name.substring(0, maxCharLength) + "..." : d.name) .on("mouseover", function (event, d) { - // Repeat the highlight effect here for consistency svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) - // .attr("r", NODE_RADIUS + 5); .each(function () { - // 'this' refers to the individual SVG circle elements var currentRadius = d3.select(this).attr("r"); d3.select(this).attr("r", parseFloat(currentRadius) + 5); }); @@ -325,6 +329,7 @@ document$.subscribe(function () { tooltip.html(d.id) .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); + d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") @@ -334,6 +339,9 @@ document$.subscribe(function () { tooltip.transition() .duration(500) .style("opacity", 0); + d3.select(this).attr("r", function (d, i) { + return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; + }); }); // Apply links on nodes From 7ad4babe7f8ea50d75ede7b455406c1218f71a73 Mon Sep 17 00:00:00 2001 From: niclas Date: Thu, 29 Feb 2024 09:19:48 +0100 Subject: [PATCH 4/6] Add [graph] galaxy visualisation while hovering --- .../docs/01_attachements/javascripts/graph.js | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index a65d8e1..80b13ac 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -80,9 +80,30 @@ document$.subscribe(function () { // Extract unique galaxy names from data const galaxies = Array.from(new Set(data.flatMap(d => [d.sourceGalaxy, d.targetGalaxy]))); - // Create a color scale using D3's scaleOrdinal and a color scheme - const colorScale = d3.scaleOrdinal(d3.schemeTableau10) - .domain(galaxies); // Maps galaxy names to colors in the scheme + const colorScheme = [ + '#E63946', // Red + '#F1FAEE', // Off White + '#A8DADC', // Light Blue + '#457B9D', // Medium Blue + '#1D3557', // Dark Blue + '#F4A261', // Sandy Brown + '#2A9D8F', // Teal + '#E9C46A', // Saffron + '#F77F00', // Orange + '#D62828', // Dark Red + '#023E8A', // Royal Blue + '#0077B6', // Light Sea Blue + '#0096C7', // Sky Blue + '#00B4D8', // Bright Sky Blue + '#48CAE4', // Light Blue + '#90E0EF', // Powder Blue + '#ADE8F4', // Pale Cerulean + '#CAF0F8', // Blithe Blue + '#FFBA08', // Selective Yellow + '#FFD60A' // Naples Yellow + ]; + const colorScale = d3.scaleOrdinal(colorScheme) + .domain(galaxies); var nodes = Array.from(new Set(data.flatMap(d => [d.source, d.target]))) .map(id => ({ @@ -113,7 +134,7 @@ document$.subscribe(function () { .force("link", d3.forceLink(links).id(d => d.id).distance(linkDistance)) .force("charge", d3.forceManyBody().strength(-30)) .force("center", d3.forceCenter(width / 2, height / 2)) - .alphaDecay(0.02); // A lower value, adjust as needed + .alphaDecay(0.05); // A lower value, adjust as needed // Create links var link = svg.append("g") @@ -148,18 +169,24 @@ document$.subscribe(function () { .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); + svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .style("font-weight", "bold") + .style("font-size", "14px"); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); }) - .on("mouseout", function (d) { + .on("mouseout", function (event, d) { tooltip.transition() .duration(500) .style("opacity", 0); d3.select(this).attr("r", function (d, i) { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }); + svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .style("font-weight", "normal") + .style("font-size", "12px"); }); // Apply links on nodes @@ -256,7 +283,7 @@ document$.subscribe(function () { .style("text-anchor", "start") .style("fill", "grey") .style("font-size", "12px") - // .text(d => d.name); + .attr("class", d => "legend-text galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .text(d => d.name.length > maxCharLength ? d.name.substring(0, maxCharLength) + "..." : d.name) .on("mouseover", function (event, d) { svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) @@ -330,18 +357,24 @@ document$.subscribe(function () { .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); + svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .style("font-weight", "bold") + .style("font-size", "14px"); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); }) - .on("mouseout", function (d) { + .on("mouseout", function (event, d) { tooltip.transition() .duration(500) .style("opacity", 0); d3.select(this).attr("r", function (d, i) { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }); + svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) + .style("font-weight", "normal") + .style("font-size", "12px"); }); // Apply links on nodes From 34b8ce4f3cbee5f4ebc9860df898d9538fb8dff6 Mon Sep 17 00:00:00 2001 From: niclas Date: Thu, 29 Feb 2024 11:41:59 +0100 Subject: [PATCH 5/6] Add [graph] opacity adjustment --- .../docs/01_attachements/javascripts/graph.js | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index 80b13ac..226d43b 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -132,7 +132,7 @@ document$.subscribe(function () { var simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).id(d => d.id).distance(linkDistance)) - .force("charge", d3.forceManyBody().strength(-30)) + .force("charge", d3.forceManyBody().strength(-50).distanceMax(500)) .force("center", d3.forceCenter(width / 2, height / 2)) .alphaDecay(0.05); // A lower value, adjust as needed @@ -143,7 +143,7 @@ document$.subscribe(function () { .selectAll("line") .data(links) .enter().append("line") - .attr("stroke-width", d => Math.sqrt(d.value)); + .attr("stroke-width", 1); // Create nodes var node = svg.append("g") @@ -168,10 +168,19 @@ document$.subscribe(function () { tooltip.html(d.id) .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); - d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); + node.style("opacity", 0.1); + link.style("opacity", 0.1); + d3.select(this) + .attr("r", parseFloat(d3.select(this).attr("r")) + 5) + .style("opacity", 1); svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .style("font-weight", "bold") .style("font-size", "14px"); + link.filter(l => l.source.id === d.id || l.target.id === d.id) + .attr("stroke-width", 3) + .style("opacity", 1); + node.filter(n => n.id === d.id || links.some(l => (l.source.id === d.id && l.target.id === n.id) || (l.target.id === d.id && l.source.id === n.id))) + .style("opacity", 1); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") @@ -181,14 +190,20 @@ document$.subscribe(function () { tooltip.transition() .duration(500) .style("opacity", 0); + node.style("opacity", 1); + link.style("opacity", 1); d3.select(this).attr("r", function (d, i) { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }); svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .style("font-weight", "normal") .style("font-size", "12px"); + link.filter(l => l.source.id === d.id || l.target.id === d.id) + .attr("stroke-width", 1); + node.filter(n => n.id === d.id || links.some(l => (l.source.id === d.id && l.target.id === n.id) || (l.target.id === d.id && l.source.id === n.id))) }); + // Apply links on nodes node.on("dblclick", function (event, d) { location.href = d.path; @@ -247,16 +262,17 @@ document$.subscribe(function () { .attr("class", "legend-item") .attr("transform", (d, i) => `translate(0, ${i * 20})`); - legendItem.append("rect") // change node radius info TODO + legendItem.append("rect") .attr("width", 12) .attr("height", 12) .style("fill", d => d.color) .on("mouseover", function (event, d) { - // Highlight all nodes associated with this galaxy + node.style("opacity", 0.1); + link.style("opacity", 0.1); svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .each(function () { var currentRadius = d3.select(this).attr("r"); - d3.select(this).attr("r", parseFloat(currentRadius) + 5); + d3.select(this).style("opacity", 1); }); tooltip.transition() .duration(200) @@ -266,11 +282,8 @@ document$.subscribe(function () { .style("top", (event.pageY - 28) + "px"); }) .on("mouseout", function (event, d) { - // Remove highlight from all nodes - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) - .attr("r", function (d, i) { - return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; - }); + node.style("opacity", 1); + link.style("opacity", 1); tooltip.transition() .duration(500) .style("opacity", 0); @@ -286,10 +299,11 @@ document$.subscribe(function () { .attr("class", d => "legend-text galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .text(d => d.name.length > maxCharLength ? d.name.substring(0, maxCharLength) + "..." : d.name) .on("mouseover", function (event, d) { + node.style("opacity", 0.1); + link.style("opacity", 0.1); svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .each(function () { - var currentRadius = d3.select(this).attr("r"); - d3.select(this).attr("r", parseFloat(currentRadius) + 5); + d3.select(this).style("opacity", 1); }); tooltip.transition() .duration(200) @@ -299,10 +313,8 @@ document$.subscribe(function () { .style("top", (event.pageY - 28) + "px"); }) .on("mouseout", function (event, d) { - svg.selectAll(".galaxy-" + d.name.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) - .attr("r", function (d, i) { - return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; - }); + node.style("opacity", 1); + link.style("opacity", 1); tooltip.transition() .duration(500) .style("opacity", 0); @@ -356,10 +368,19 @@ document$.subscribe(function () { tooltip.html(d.id) .style("left", (event.pageX) + "px") .style("top", (event.pageY - 28) + "px"); - d3.select(this).attr("r", parseFloat(d3.select(this).attr("r")) + 5); + node.style("opacity", 0.1); + link.style("opacity", 0.1); + d3.select(this) + .attr("r", parseFloat(d3.select(this).attr("r")) + 5) + .style("opacity", 1); svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .style("font-weight", "bold") .style("font-size", "14px"); + link.filter(l => l.source.id === d.id || l.target.id === d.id) + .attr("stroke-width", 3) + .style("opacity", 1); + node.filter(n => n.id === d.id || links.some(l => (l.source.id === d.id && l.target.id === n.id) || (l.target.id === d.id && l.source.id === n.id))) + .style("opacity", 1); }) .on("mousemove", function (event) { tooltip.style("left", (event.pageX) + "px") @@ -369,12 +390,17 @@ document$.subscribe(function () { tooltip.transition() .duration(500) .style("opacity", 0); + node.style("opacity", 1); + link.style("opacity", 1); d3.select(this).attr("r", function (d, i) { return d.id === Parent_Node.id ? NODE_RADIUS + 5 : NODE_RADIUS; }); svg.selectAll(".legend-text.galaxy-" + d.galaxy.replace(/\s+/g, '-').replace(/[\s.]/g, '-')) .style("font-weight", "normal") .style("font-size", "12px"); + link.filter(l => l.source.id === d.id || l.target.id === d.id) + .attr("stroke-width", 1); + node.filter(n => n.id === d.id || links.some(l => (l.source.id === d.id && l.target.id === n.id) || (l.target.id === d.id && l.source.id === n.id))) }); // Apply links on nodes From 7ff99f520167c215b5b022fad7ca94b50199e383 Mon Sep 17 00:00:00 2001 From: niclas Date: Thu, 29 Feb 2024 16:30:18 +0100 Subject: [PATCH 6/6] Add [graph] pre filtering for large data --- .../docs/01_attachements/javascripts/graph.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js index 226d43b..cffb5ba 100644 --- a/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js +++ b/tools/mkdocs/site/docs/01_attachements/javascripts/graph.js @@ -5,6 +5,12 @@ document$.subscribe(function () { const Parent_Node_COLOR = "#ff0000"; + function applyTableFilter(tf) { + var valuesToSelect = ['1', '2', '3']; + tf.setFilterValue(4, valuesToSelect); + tf.filter(); + }; + function parseFilteredTable(tf, allData) { var data = []; tf.getFilteredData().forEach((row, i) => { @@ -427,6 +433,8 @@ document$.subscribe(function () { // Restart the simulation with new data simulation.nodes(nodes); simulation.force("link").links(links); + linkDistance = Math.sqrt((width * height) / nodes.length); + simulation.force("link").distance(linkDistance); simulation.alpha(1).restart(); } }); @@ -473,7 +481,13 @@ document$.subscribe(function () { }); tf.init(); - var data = parseTable(table); + var allData = parseTable(table); + if (allData.length > 1000) { + applyTableFilter(tf); + data = parseFilteredTable(tf, allData); + } else { + data = allData; + } var graphId = "graph" + index; var div = document.createElement("div"); div.id = graphId; @@ -482,7 +496,7 @@ document$.subscribe(function () { // Listen for table filtering events tf.emitter.on(['after-filtering'], function () { - filterTableAndGraph(tf, simulation, data); + filterTableAndGraph(tf, simulation, allData); }); } });