2020-11-30 11:29:34 +00:00
import Cytoscape from "cytoscape" ;
var nodeHtmlLabel = require ( 'cytoscape-node-html-label' ) ;
const Graph = ( { el , graphdata , current } ) => {
nodeHtmlLabel ( Cytoscape ) ;
var cy = Cytoscape ( {
container : el ,
elements : graphdata ,
style : [ {
selector : "node" ,
style : {
"background-color" : el => el . data ( "id" ) === current ? '#5221c4' : "#666" ,
"font-size" : "10px" ,
"width" : "20px" ,
"height" : "20px"
//"label": el => el.data("id") === current ? "" : el.data('title') ? el.data("title").slice(0,16) : el.data("id")
}
} , {
selector : "label" ,
style : { "font-size" : "12px" } ,
} ,
{
selector : 'edge' ,
style : {
'width' : 2 ,
"height" : 200 ,
2021-10-23 02:43:44 +00:00
'line-color' : '#ffffff' ,
2020-11-30 11:29:34 +00:00
'target-arrow-color' : '#ccc' ,
'target-arrow-shape' : 'triangle' ,
'curve-style' : 'bezier'
}
} ] ,
layout : {
name : 'circle' ,
fit : true , // whether to fit the viewport to the graph
padding : 32 , // the padding on fit
boundingBox : undefined , // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap : true , // prevents node overlap, may overflow boundingBox and radius if not enough space
nodeDimensionsIncludeLabels : false , // Excludes the label when calculating node bounding boxes for the layout algorithm
spacingFactor : 0.9 , // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
radius : 180 , // the radius of the circle
startAngle : - 2 / 4 * Math . PI , // where nodes start in radians
//sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)
clockwise : true , // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)
sort : undefined , // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
animate : false , // whether to transition the node positions
animationDuration : 500 , // duration of animation in ms if enabled
animationEasing : undefined , // easing of animation if enabled
//animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready : undefined , // callback on layoutready
stop : undefined , // callback on layoutstop
2021-10-23 02:43:44 +00:00
transform : function ( node , position ) { return position ; } // transform a given node position. Useful for changing flow direction in discrete layouts
2020-11-30 11:29:34 +00:00
} ,
zoom : 10 ,
hideEdgesOnViewport : false ,
wheelSensitivity : 0.2 ,
} )
2021-10-23 02:43:44 +00:00
2020-11-30 11:29:34 +00:00
cy . nodeHtmlLabel ( [ {
query : "node" ,
halign : "top" ,
valign : "center" ,
cssClass : 'label' ,
tpl : el => {
//el.data("id") === current ? "" : el.data('title') ? el.data("title").slice(0,16) : el.data("id")
const label = el . id === current ? "" : el . title ? el . title : el . id
return ` <div title=" ${ el . title ? el . title : el . id } " style='font-weight:400; margin-top:32px;max-width:180px;font-size:12px;color:white;cursor:pointer;'> ${ label } </div> `
} } ] ,
{
enablePointerEvents : true
}
)
return cy
}
2020-12-06 19:40:20 +00:00
export const Network = ( { el , graphdata , current , routeHandler , allNodes } ) => {
2020-11-30 11:29:34 +00:00
var jsnx = require ( 'jsnetworkx' ) ;
2021-10-23 02:43:44 +00:00
2020-12-01 03:28:42 +00:00
//const grouper = (id) => id === "index" ? 1 : (id === "codesheet" ? 2 : 3)
2020-11-30 11:29:34 +00:00
var currentnode = graphdata . filter ( g => g . data . id === current ) [ 0 ]
2020-12-01 03:28:42 +00:00
currentnode = [ currentnode . data . id , {
label : current === "index" ? "HOME" : currentnode . data . title ? currentnode . data . title : currentnode . data . id ,
href : current === "index" ? "/" : ` /note/ ${ currentnode . data . id } ` ,
//group:grouper(current)
} ] ;
//var currentTargetNames = graphdata.filter(g => g.data.source === current).map(e => e.data.target)
//var currentTargetNodes = graphdata.filter(g => currentTargetNames.includes(g.data.id))
2020-11-30 11:29:34 +00:00
var othernodes , edges ;
if ( allNodes ) {
2020-12-01 03:28:42 +00:00
othernodes = graphdata . filter ( g => ( g . data . id !== current ) && ! g . data . source )
2020-11-30 11:29:34 +00:00
othernodes = othernodes . map ( on => [ on . data . id , {
2020-12-01 03:28:42 +00:00
label : on . data . title ? on . data . title : on . data . id ,
href : on . data . id === "index" ? "/" : ` /note/ ${ on . data . id } ` ,
//group: grouper(on.data.id)
2020-11-30 11:29:34 +00:00
}
] )
2020-12-01 03:28:42 +00:00
//console.log(othernodes)
2020-11-30 11:29:34 +00:00
edges = graphdata . filter ( g => g . data . source )
edges = edges . map ( e => [ e . data . source , e . data . target ] )
}
else {
2020-12-01 03:28:42 +00:00
//console.log("else")
2020-11-30 11:29:34 +00:00
var indexnode = graphdata . filter ( g => g . data . id === "index" ) [ 0 ]
2021-10-23 02:43:44 +00:00
indexnode = [ "Home" , {
2020-11-30 11:29:34 +00:00
width : 30 ,
height : 30 ,
2020-12-01 03:28:42 +00:00
weight : 1 ,
2020-11-30 11:29:34 +00:00
href : ` / ` ,
title : "Home" ,
fill : "blueviolet" ,
2021-10-23 02:43:44 +00:00
2020-11-30 11:29:34 +00:00
} ]
var currentRawEdges = graphdata . filter ( g => g . data . source === current )
2020-12-01 03:28:42 +00:00
edges = currentRawEdges . map ( ce => [ ce . data . source , ce . data . target , { weight : 1 } ] )
2020-11-30 11:29:34 +00:00
var currentTargetNames = currentRawEdges . map ( ie => ie . data . target )
var currentTargets = graphdata . filter ( g => currentTargetNames . includes ( g . data . id ) )
othernodes = currentTargets . map ( ct => [ ct . data . id , { size : 6 , href : ` /note/ ${ ct . data . id } ` } ] )
2020-12-06 19:40:20 +00:00
if ( current !== "index" ) { othernodes . push ( indexnode ) }
//othernodes = [indexnode, ...othernodes]
2020-11-30 11:29:34 +00:00
}
2020-12-01 03:28:42 +00:00
var G = new jsnx . DiGraph ( ) ;
2020-11-30 11:29:34 +00:00
G . addNodesFrom (
[
currentnode ,
... othernodes ,
2021-10-23 02:43:44 +00:00
] ,
2020-12-01 03:28:42 +00:00
{ color : '#999999' , width : 40 , height : 40 }
2020-11-30 11:29:34 +00:00
) ;
G . addEdgesFrom ( edges ) ;
jsnx . draw ( G , {
element : el ,
withLabels : true ,
labelStyle : {
2020-12-01 03:28:42 +00:00
color : "#333" ,
fill : function ( n ) {
2021-10-23 02:43:44 +00:00
return n . node === current ? "#fff" : "#000"
2020-12-01 03:28:42 +00:00
}
2020-11-30 11:29:34 +00:00
} ,
labelAttr : {
class : "node-label" ,
y : 16 ,
click : function ( l ) {
this . addEventListener ( "click" , function ( ) {
2020-12-06 19:40:20 +00:00
routeHandler ( l . data . href )
2020-11-30 11:29:34 +00:00
} )
}
} ,
2020-12-01 20:30:06 +00:00
weighted : true ,
2020-11-30 11:29:34 +00:00
layoutAttr : {
2020-12-06 19:40:20 +00:00
linkDistance : 200 ,
2020-12-01 20:30:06 +00:00
linkStrength : 1.5 ,
2020-12-06 19:40:20 +00:00
friction : 0.3 ,
charge : - 180 ,
//charge:function(c){ return -80},
2020-11-30 11:29:34 +00:00
} ,
nodeStyle : {
2021-10-23 02:43:44 +00:00
fill : function ( d ) {
2020-12-01 03:28:42 +00:00
return "#999"
//console.log("group", d.data.group)
2021-10-23 02:43:44 +00:00
//return color(d.data.group);
2020-12-01 03:28:42 +00:00
} ,
stroke : 'none'
2020-11-30 11:29:34 +00:00
} ,
nodeAttr : {
2020-12-01 03:28:42 +00:00
class : "node-node" ,
2020-11-30 11:29:34 +00:00
click : function ( l ) {
this . addEventListener ( "click" , function ( ) {
2020-12-01 03:28:42 +00:00
console . log ( "lll" , l . data ) ;
2020-12-06 19:40:20 +00:00
routeHandler ( l . data . href )
2020-11-30 11:29:34 +00:00
} )
}
} ,
2020-12-01 20:30:06 +00:00
2020-11-30 11:29:34 +00:00
edgeStyle : {
2020-12-01 20:30:06 +00:00
height : 120 ,
strokeWidth : 2 ,
stroke : "#999"
2020-11-30 11:29:34 +00:00
}
} , true ) ;
return G
}
2021-10-23 02:43:44 +00:00
export default Graph ;