mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-30 20:41:33 +08:00 
			
		
		
		
	Merge pull request #700 from CobriMediaJulien/develop
New Features for note map
This commit is contained in:
		
						commit
						4077a01019
					
				| @ -28,6 +28,51 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|             font-size: 130%; |             font-size: 130%; | ||||||
|             padding: 1px 10px 1px 10px; |             padding: 1px 10px 1px 10px; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         /* Style Ui Element to Drag Nodes */ | ||||||
|  |         .fixnodes-type-switcher { | ||||||
|  |             position: absolute;  | ||||||
|  |             top: 10px;  | ||||||
|  |             left: 45%; | ||||||
|  |             z-index: 10; /* should be below dropdown (note actions) */ | ||||||
|  |             border-radius:0.2rem; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* Start of styling the slider */ | ||||||
|  |             input[type="range"] { | ||||||
|  |    | ||||||
|  |             /* removing default appearance */ | ||||||
|  |             -webkit-appearance: none; | ||||||
|  |             appearance: none;  | ||||||
|  |             margin-left: 15px; | ||||||
|  |             width:50% | ||||||
|  |              | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /* Changing slider tracker */ | ||||||
|  |         input[type="range"]::-webkit-slider-runnable-track { | ||||||
|  |         height: 6px; | ||||||
|  |         background: #ccc; | ||||||
|  |         border-radius: 16px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /* Changing Slider Thumb*/ | ||||||
|  |         input[type="range"]::-webkit-slider-thumb { | ||||||
|  |         /* removing default appearance */ | ||||||
|  |         -webkit-appearance: none; | ||||||
|  |         appearance: none;  | ||||||
|  |         /* creating a custom design */ | ||||||
|  |         height: 15px; | ||||||
|  |         width: 15px; | ||||||
|  |         margin-top:-4px; | ||||||
|  |         background-color: #661822; | ||||||
|  |         border-radius: 50%; | ||||||
|  | 
 | ||||||
|  |         /* End of styling the slider */ | ||||||
|  | 
 | ||||||
|     </style> |     </style> | ||||||
|      |      | ||||||
|     <div class="btn-group btn-group-sm map-type-switcher" role="group"> |     <div class="btn-group btn-group-sm map-type-switcher" role="group"> | ||||||
| @ -35,6 +80,14 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|       <button type="button" class="btn bx bx-sitemap" title="${t("note-map.button-tree-map")}" data-type="tree"></button> |       <button type="button" class="btn bx bx-sitemap" title="${t("note-map.button-tree-map")}" data-type="tree"></button> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|  |     <! UI for dragging Notes and link force > | ||||||
|  | 
 | ||||||
|  |      <div class=" btn-group-sm fixnodes-type-switcher" role="group"> | ||||||
|  |       <button type="button" class="btn bx bx-expand" title="Fixation" data-type="moveable"></button> | ||||||
|  |       <input type="range" class=" slider" min="1" title="Link distance" max="100" value="40" > | ||||||
|  |        | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|     <div class="style-resolver"></div> |     <div class="style-resolver"></div> | ||||||
| 
 | 
 | ||||||
|     <div class="note-map-container"></div> |     <div class="note-map-container"></div> | ||||||
| @ -43,7 +96,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
| export default class NoteMapWidget extends NoteContextAwareWidget { | export default class NoteMapWidget extends NoteContextAwareWidget { | ||||||
|     constructor(widgetMode) { |     constructor(widgetMode) { | ||||||
|         super(); |         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'
 |         this.widgetMode = widgetMode; // 'type' or 'ribbon'
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -64,6 +117,13 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             await attributeService.setLabel(this.noteId, 'mapType', type); |             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(); |         super.doRender(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -92,13 +152,61 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
| 
 | 
 | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH); |         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]) |         this.graph = ForceGraph()(this.$container[0]) | ||||||
|             .width(this.$container.width()) |             .width(this.$container.width()) | ||||||
|             .height(this.$container.height()) |             .height(this.$container.height()) | ||||||
|             .onZoom(zoom => this.setZoomLevel(zoom.k)) |             .onZoom(zoom => this.setZoomLevel(zoom.k)) | ||||||
|             .d3AlphaDecay(0.01) |             .d3AlphaDecay(0.01) | ||||||
|             .d3VelocityDecay(0.08) |             .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, ctx) => this.paintNode(node, this.getColorForNode(node), ctx)) | ||||||
|             .nodePointerAreaPaint((node, color, ctx) => { |             .nodePointerAreaPaint((node, color, ctx) => { | ||||||
|                 ctx.fillStyle = color; |                 ctx.fillStyle = color; | ||||||
| @ -109,10 +217,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             .nodeLabel(node => esc(node.name)) |             .nodeLabel(node => esc(node.name)) | ||||||
|             .maxZoom(7) |             .maxZoom(7) | ||||||
|             .warmupTicks(30) |             .warmupTicks(30) | ||||||
|             .linkDirectionalArrowLength(5) |  | ||||||
|             .linkDirectionalArrowRelPos(1) |  | ||||||
|             .linkWidth(1) |  | ||||||
|             .linkColor(() => this.css.mutedTextColor) |  | ||||||
|             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) |             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) | ||||||
|             .onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e)); |             .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 magnifiedRatio = Math.pow(nodeLinkRatio, 1.5); | ||||||
|         const charge = -20 / magnifiedRatio; |         const charge = -20 / magnifiedRatio; | ||||||
|         const boundedCharge = Math.min(-3, charge); |         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('center').strength(0.2); | ||||||
|         this.graph.d3Force('charge').strength(boundedCharge); |         this.graph.d3Force('charge').strength(boundedCharge); | ||||||
|         this.graph.d3Force('charge').distanceMax(1000); |         this.graph.d3Force('charge').distanceMax(1000); | ||||||
| @ -201,7 +312,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
| 
 | 
 | ||||||
|         ctx.fillStyle = color; |         ctx.fillStyle = color; | ||||||
|         ctx.beginPath(); |         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(); |         ctx.fill(); | ||||||
| 
 | 
 | ||||||
|         const toRender = this.zoomLevel > 2 |         const toRender = this.zoomLevel > 2 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran