Skip to content

Commit

Permalink
Merge pull request #140 from togostanza/feature/fix-force-graph-selec…
Browse files Browse the repository at this point in the history
…tion

 ForceGraph/fix selection
  • Loading branch information
penqe authored May 30, 2024
2 parents b697320 + 04eb6f8 commit 280ee28
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 152 deletions.
16 changes: 0 additions & 16 deletions stanzas/chord-diagram/drawChordDiagram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,7 @@ export function drawChordDiagram(svg, nodes, edges, { symbols, ...params }) {
});

// Nodes (arcs)

chords.groups.forEach((node) => {
// edgeSym,
// edgeWidthSym,
// sourceNodeSym,
// targetNodeSym,
// nodeSizeSym,
// nodeColorSym,
// groupSym,
// edgeColorSym,
// nodeLabelSym,
// idSym,
// nodeBorderColorSym,
// isPairEdge,

node.id = nodes[node.index][params.nodeLabelParams.dataKey];

node[symbols.nodeColorSym] = edgeColorScale("" + node.index);
Expand Down Expand Up @@ -102,8 +88,6 @@ export function drawChordDiagram(svg, nodes, edges, { symbols, ...params }) {
.classed("chord", true)
.style("fill", (d) => chords.groups[d.source.index][symbols.nodeColorSym]);

console.log("ribbons", ribbons);

const arcsG = rootGroup
.append("g")
.classed("arcs", true)
Expand Down
50 changes: 5 additions & 45 deletions stanzas/force-graph/drawForceLayout.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as d3 from "d3";
import { addHighlightOnHover } from "../../lib/graphHighlight";

function straightLink(d) {
const start = { x: d.source.x, y: d.source.y };
Expand Down Expand Up @@ -181,15 +182,15 @@ export default function (
.data(nodes)
.enter()
.append("g")
.attr("class", "node-group")
.attr("class", "node")
.attr("transform", (d) => {
return `translate(${d.x},${d.y})`;
})
.call(drag(simulation));

const nodeCircles = nodeGroups
.append("circle")
.attr("class", "node")

.attr("cx", 0)
.attr("cy", 0)
.attr("r", (d) => d[symbols.nodeSizeSym])
Expand All @@ -210,14 +211,12 @@ export default function (
.text((d) => d[nodeLabelParams.dataKey]);
}

let isDragging = false;

function drag(simulation) {
function dragstarted(event) {
if (!event.active) {
simulation.alphaTarget(0.3).restart();
}
isDragging = true;

event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
Expand All @@ -228,7 +227,6 @@ export default function (
}

function dragended(event) {
isDragging = false;
if (!event.active) {
simulation.alphaTarget(0);
}
Expand All @@ -244,44 +242,6 @@ export default function (
}

if (highlightAdjEdges) {
nodeGroups.on("mouseover", function (e, d) {
if (isDragging) {
return;
}
// highlight current node
d3.select(this).classed("active", true);
// fade out all other nodes, highlight a little connected ones
nodeGroups
.classed("fadeout", (p) => d !== p)
.classed("half-active", (p) => {
return (
p !== d &&
d[symbols.edgeSym].some(
(edge) =>
edge[symbols.sourceNodeSym] === p ||
edge[symbols.targetNodeSym] === p
)
);
});

// fadeout not connected edges, highlight connected ones
links
.classed("fadeout", (p) => !d[symbols.edgeSym].includes(p))
.classed("active", (p) => d[symbols.edgeSym].includes(p));
});

nodeGroups.on("mouseleave", function () {
if (isDragging) {
return;
}
links
.classed("active", false)
.classed("fadeout", false)
.classed("half-active", false);
nodeGroups
.classed("active", false)
.classed("fadeout", false)
.classed("half-active", false);
});
addHighlightOnHover(symbols, nodes, nodeGroups, links);
}
}
74 changes: 21 additions & 53 deletions stanzas/force-graph/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import MetaStanza from "../../lib/MetaStanza";
import { handleApiError } from "../../lib/apiError";
import drawForceLayout from "./drawForceLayout";

import { getMarginsFromCSSString } from "@/lib/utils";

import {
appendCustomCss,
downloadCSVMenuItem,
Expand All @@ -22,7 +24,7 @@ import {
export default class ForceGraph extends MetaStanza {
_graphArea;
selectedEventParams = {
targetElementSelector: ".node-group",
targetElementSelector: ".node",
selectedElementClassName: "-selected",
selectedElementSelector: ".-selected",
idPath: "id",
Expand Down Expand Up @@ -175,25 +177,27 @@ export default class ForceGraph extends MetaStanza {
symbols,
});

this._graphArea.selectAll("circle.node").on("click", (_, d) => {
toggleSelectIds({
selectedIds: this.selectedIds,
targetId: d.id,
});
updateSelectedElementClassNameForD3({
drawing: this._graphArea,
selectedIds: this.selectedIds,
...this.selectedEventParams,
});
if (this.params["event-outgoing_change_selected_nodes"]) {
emitSelectedEvent({
rootElement: this.element,
if (this.params["event-outgoing_change_selected_nodes"]) {
this._graphArea.selectAll(".node").on("click", (_, d) => {
toggleSelectIds({
selectedIds: this.selectedIds,
targetId: d.id,
});
updateSelectedElementClassNameForD3({
drawing: this._graphArea,
selectedIds: this.selectedIds,
dataUrl: this.params["data-url"],
...this.selectedEventParams,
});
}
});
if (this.params["event-outgoing_change_selected_nodes"]) {
emitSelectedEvent({
rootElement: this.element,
targetId: d.id,
selectedIds: this.selectedIds,
dataUrl: this.params["data-url"],
});
}
});
}
};

handleApiError({
Expand All @@ -219,39 +223,3 @@ export default class ForceGraph extends MetaStanza {
}
}
}

function getMarginsFromCSSString(str) {
const splitted = str.trim().split(/\W+/);

const res = {
TOP: 0,
RIGHT: 0,
BOTTOM: 0,
LEFT: 0,
};

switch (splitted.length) {
case 1:
res.TOP = res.RIGHT = res.BOTTOM = res.LEFT = parseInt(splitted[0]);
break;
case 2:
res.TOP = res.BOTTOM = parseInt(splitted[0]);
res.LEFT = res.RIGHT = parseInt(splitted[1]);
break;
case 3:
res.TOP = parseInt(splitted[0]);
res.LEFT = res.RIGHT = parseInt(splitted[1]);
res.BOTTOM = parseInt(splitted[2]);
break;
case 4:
res.TOP = parseInt(splitted[0]);
res.RIGHT = parseInt(splitted[1]);
res.BOTTOM = parseInt(splitted[2]);
res.LEFT = parseInt(splitted[3]);
break;
default:
break;
}

return res;
}
2 changes: 1 addition & 1 deletion stanzas/force-graph/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
"stanza:description": "Color applied to the selected item"
},
{
"stanza:key": "--togostanza-edge-default_color",
"stanza:key": "--togostanza-edge-color",
"stanza:type": "color",
"stanza:default": "#bdbdbd",
"stanza:description": "Egdes default color"
Expand Down
68 changes: 31 additions & 37 deletions stanzas/force-graph/style.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
// Load the repository-wide global style here. The actual file is located at ../common.scss for details.
@use "@/common.scss";

svg > defs > marker > path {
fill: var(--togostanza-edge-default_color);
}

.label,
.node,
.link,
.active,
.fadeout,
.half-active {
.-active,
.-fadeout,
.-half-active {
transition: all 0.1s ease-in-out;
transition-property: opacity, stroke-width, stroke-opacity;
}
Expand All @@ -24,51 +20,49 @@ svg > defs > marker > path {
stroke: var(--togostanza-border-color);
stroke-width: var(--togostanza-border-width);
cursor: pointer;
}

.node-group {
&.-selected {
text {
fill: var(--togostanza-theme-selected_border_color);
}
opacity: 1 !important;
}
}

.link {
stroke-opacity: var(--togostanza-edge-opacity);
stroke-linecap: round;
fill: none;
stroke: var(--togostanza-edge-default_color);
}

.active {
> .node {
&.-active {
opacity: 1;
stroke-width: calc(var(--togostanza-border-width) * 2.5px);
stroke-opacity: 1;
}
> .link {
stroke-opacity: 1;

&.-half-active {
opacity: calc(var(--togostanza-fadeout-opacity) + 0.3);
stroke-width: calc(var(--togostanza-border-width) * 1.6px);
}
> .label {
opacity: 1;

&.-fadeout {
opacity: var(--togostanza-fadeout-opacity);
}
}

.fadeout {
opacity: 0.05;
> .link {
stroke-opacity: 0.05;
.link {
stroke: var(--togostanza-edge-color);
opacity: var(--togostanza-edge-opacity);

&.-fadeout {
opacity: calc(
var(--togostanza-fadeout-opacity) * var(--togostanza-edge-opacity)
);
}
}

.half-active {
opacity: 0.8;
> .node {
stroke-width: calc(var(--togostanza-border-width) * 1.6px);
stroke-opacity: 0.8;
svg {
& > defs > marker > path {
fill: var(--togostanza-edge-color);
}

> .label {
opacity: 0.6;
&:has(.-selected) {
.node {
opacity: var(--togostanza-fadeout-opacity);
}
.link {
opacity: var(--togostanza-fadeout-opacity);
}
}
}

0 comments on commit 280ee28

Please sign in to comment.