export default class NoteMapWidget extends NoteContextAwareWidget {
constructor(widgetMode) {
super();
-
+ this.fixNodes = false; // needed to save the status of the UI element. Is set later in the code
this.widgetMode = widgetMode; // 'type' or 'ribbon'
}
@@ -64,6 +117,13 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
await attributeService.setLabel(this.noteId, 'mapType', type);
});
+ // Reading the status of the Drag nodes Ui element. Changing it´s color when activated. Reading Force value of the link distance.
+
+ this.$widget.find('.fixnodes-type-switcher').on('click', async event => {
+ this.fixNodes = !this.fixNodes;
+ event.target.style.backgroundColor = this.fixNodes ? '#661822' : 'transparent';
+ });
+
super.doRender();
}
@@ -92,13 +152,61 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH);
+ //variables for the hover effekt. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
+
+ let hoverNode = null;
+ const highlightLinks = new Set();
+ const neighbours = new Set();
+
this.graph = ForceGraph()(this.$container[0])
.width(this.$container.width())
.height(this.$container.height())
.onZoom(zoom => this.setZoomLevel(zoom.k))
.d3AlphaDecay(0.01)
.d3VelocityDecay(0.08)
- .nodeCanvasObject((node, ctx) => this.paintNode(node, this.getColorForNode(node), ctx))
+
+ //Code to fixate nodes when dragged
+ .onNodeDragEnd(node => {
+ if (this.fixNodes) {
+ node.fx = node.x;
+ node.fy = node.y;
+ } else {
+ node.fx = null;
+ node.fy = null;
+ }
+ })
+ //check if hovered and set the hovernode variable, saving the hovered node object into it. Clear links variable everytime you hover. Without clearing links will stay highlighted
+ .onNodeHover(node => {
+ hoverNode = node || null;
+ highlightLinks.clear();
+ })
+
+ // set link width to immitate a highlight effekt. Checking the condition if any links are saved in the previous defined set highlightlinks
+ .linkWidth(link => (highlightLinks.has(link) ? 3 : 0.4))
+ .linkColor(link => (highlightLinks.has(link) ? 'white' : this.css.mutedTextColor))
+ .linkDirectionalArrowLength(4)
+ .linkDirectionalArrowRelPos(0.95)
+
+ // main code for highlighting hovered nodes and neighbours. here we "style" the nodes. the nodes are rendered several hundred times per second.
+ .nodeCanvasObject((node, ctx) => {
+ if (hoverNode == node) { //paint only hovered node
+ this.paintNode(node, '#661822', ctx);
+ neighbours.clear(); //clearing neighbours or the effect would be maintained after hovering is over
+ for (const link of data.links) { //check if node is part of a link in the canvas, if so add it´s neighbours and related links to the previous defined variables to paint the nodes
+ if (link.source.id == node.id || link.target.id == node.id) {
+ neighbours.add(link.source);
+ neighbours.add(link.target);
+ highlightLinks.add(link);
+ neighbours.delete(node);
+ }
+ }
+ } else if (neighbours.has(node) && hoverNode != null) { //paint neighbours
+ this.paintNode(node, '#9d6363', ctx);
+ } else {
+ this.paintNode(node, this.getColorForNode(node), ctx); //paint rest of nodes in canvas
+ }
+ })
+
.nodePointerAreaPaint((node, ctx) => this.paintNode(node, this.getColorForNode(node), ctx))
.nodePointerAreaPaint((node, color, ctx) => {
ctx.fillStyle = color;
@@ -109,10 +217,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
.nodeLabel(node => esc(node.name))
.maxZoom(7)
.warmupTicks(30)
- .linkDirectionalArrowLength(5)
- .linkDirectionalArrowRelPos(1)
- .linkWidth(1)
- .linkColor(() => this.css.mutedTextColor)
.onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id))
.onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e));
@@ -130,8 +234,15 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
const magnifiedRatio = Math.pow(nodeLinkRatio, 1.5);
const charge = -20 / magnifiedRatio;
const boundedCharge = Math.min(-3, charge);
+ let distancevalue = 40; // default value for the link force of the nodes
+
+ this.$widget.find('.fixnodes-type-switcher input').on('change', async e => {
+ distancevalue = e.target.closest('input').value;
+ this.graph.d3Force('link').distance(distancevalue);
+
+ this.renderData(data);
+ });
- this.graph.d3Force('link').distance(40);
this.graph.d3Force('center').strength(0.2);
this.graph.d3Force('charge').strength(boundedCharge);
this.graph.d3Force('charge').distanceMax(1000);
@@ -201,7 +312,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
ctx.fillStyle = color;
ctx.beginPath();
- ctx.arc(x, y, size, 0, 2 * Math.PI, false);
+ ctx.arc(x, y, size*0.8, 0, 2 * Math.PI, false);
ctx.fill();
const toRender = this.zoomLevel > 2