Commit 09c12d64 authored by Romain Loth's avatar Romain Loth

better neighbors data structure and render

1) fixed logic where same side neighboors where computed several times (=> pass them as argument) 2) renamed updateLeftPanel to clearer updateRelatedNodesPanel 3) passed part of the color switching mecanisms to renderers, based on flags 4) adjust some css and remove some debug comments
parent 9e4afff2
......@@ -56,37 +56,37 @@
font-weight: bold;
font-size: 90%;
}
.my-legend .legend-scale ul {
margin: 0;
margin-bottom: 5px;
padding: 0;
float: left;
list-style: none;
}
.my-legend .legend-scale ul li {
font-size: 80%;
list-style: none;
margin-left: 0;
line-height: 18px;
margin-bottom: 2px;
}
.my-legend ul.legend-labels li span {
display: block;
float: left;
height: 16px;
width: 30px;
margin-right: 5px;
margin-left: 0;
border: 1px solid #999;
}
.my-legend .legend-source {
font-size: 70%;
color: #999;
clear: both;
}
.my-legend a {
color: #777;
}
.my-legend .legend-scale ul {
margin: 0;
margin-bottom: 5px;
padding: 0;
float: left;
list-style: none;
}
.my-legend .legend-scale ul li {
font-size: 80%;
list-style: none;
margin-left: 0;
line-height: 16px;
margin-bottom: 2px;
}
.my-legend ul.legend-labels li span {
display: block;
float: left;
height: 16px;
width: 30px;
margin-right: 5px;
margin-left: 0;
border: 1px solid #999;
}
.my-legend .legend-source {
font-size: 70%;
color: #999;
clear: both;
}
.my-legend a {
color: #777;
}
/*.btn-sm[normal] {*/
......
......@@ -5,7 +5,7 @@ var TW = {}
TW.colorByAtt = false;
TW.twittertimeline = false;
TW.minimap=false;
TW.getAdditionalInfo=false;// True: Activate TopPapers feature.
TW.getAdditionalInfo=true;// True: Activate TopPapers feature.
//TW.mainfile = ["db.json"];
// // TW.mainfile = "api.json";
TW.mainfile = [
......@@ -43,7 +43,7 @@ var TW = {}
// flag name is div class to be removed if false
// *and* subdirectory to import if true
// see also ProcessDivsFlags()
TW.DivsFlags["histogramModule"] = true ;
TW.DivsFlags["histogramModule"] = false ;
TW.DivsFlags["crowdsourcingModule"] = true ; // £TODO fix topPapers
TW.SystemStates = {}
......@@ -102,8 +102,13 @@ var semanticConverged=false;
// ============ < / DEVELOPER OPTIONS > ============
var showLabelsIfZoom=1.0;
TW.edgeDefaultOpacity = 0.3 // opacity when true_color
TW.edgeGreyColor = "rgba(200, 200, 200, 0.5)";
TW.edgeDefaultOpacity = 0.5 // opacity when true_color
TW.edgeGreyColor = "rgba(150, 150, 150, 0.2)";
TW.nodesGreyBorderColor = "rgba(100, 100, 100, 0.5)";
TW.selectedColor = "node" // "node" for a background like the node's color,
// "default" for note-like yellow
TW.overSampling = true // costly hi-def rendering (true => pixelRatio x 2)
// ============ < / DEVELOPER OPTIONS > ============
......
......@@ -5,7 +5,7 @@ function SelectionEngine() {
// creates the union of prevsels and currsels, if addvalue
this.SelectorEngine = (function(addvalue , prevsels , currsels ) {
console.log("addvalue, prevsels, currsels",addvalue, prevsels, currsels)
// console.log("addvalue, prevsels, currsels",addvalue, prevsels, currsels)
var targeted = []
var buffer = Object.keys(prevsels).map(Number).sort(this.sortNumber);
......@@ -19,7 +19,9 @@ function SelectionEngine() {
} else targeted = currsels;
targeted = targeted.map(Number)
console.log("targeted::", targeted)
// debug
// console.log("targeted::", targeted)
// NB new sigma: my REFA deprecated clicktype=="double"
if(targeted.length==0) return [];
......@@ -142,15 +144,30 @@ function SelectionEngine() {
* Main function for any selecting action
*
* @nodes: eg targeted array (only ids)
*
* external usage : partialGraph.states,
* updateRelatedNodesPanel();
*/
// external usage : partialGraph , updateLeftPanel_fix();
// ====================
this.MultipleSelection2 = (function(nodes,nodesDict,edgesDict) {
// =====
console.log("IN SelectionEngine.MultipleSelection2:")
console.log("nodes", nodes)
greyEverything();
var sameSideNeighbors = {}
var oppositeSideNeighbors = {}
// TW.partialGraph.states.slice(-1)[0] is the present graph state
// eg
// {categories: ["someNodeCat"]
// categoriesDict: {"someNodeCat":0} // where val 0 or 1 is type sem or soc
// opposites:
// selections:
// type:[0]}
var typeNow = TW.partialGraph.states.slice(-1)[0].type.map(Number).join("|")
// console.log ("console.loging the Type:")
// console.log (typeNow)
......@@ -167,22 +184,31 @@ function SelectionEngine() {
if(! $.isArray(nodes)) ndsids.push(nodes);
else ndsids=nodes;
for(var i in ndsids) {
s = ndsids[i];
var s = ndsids[i];
if(TW.Relations[typeNow] && TW.Relations[typeNow][s] ) {
let neigh = TW.Relations[typeNow][s]
var neigh = TW.Relations[typeNow][s]
if(neigh) {
for(var j in neigh) {
let t = neigh[j]
nodes_2_colour[t]=false;
var t = neigh[j]
// we add as neighbor to color it (except if already in targeted)
if (!nodes_2_colour[t]) nodes_2_colour[t]=false;
edges_2_colour[s+";"+t]=true;
edges_2_colour[t+";"+s]=true;
// since we're there we keep the info
if (typeof sameSideNeighbors[t] == 'undefined') {
sameSideNeighbors[t]=0
}
sameSideNeighbors[t]++
}
}
}
}
for(var i in ndsids) {
nodes_2_colour[ndsids[i]]=true;
selections[ndsids[i]]=1; // to delete please
// we make the selected (source) node active too
nodes_2_colour[s]=true;
// update GLOBAL selections dict
// (FIXME it's widely used but TW.SystemStates.selections has the same)
selections[ndsids[i]]=1;
}
}
......@@ -194,16 +220,18 @@ function SelectionEngine() {
n.customAttrs['grey'] = 0;
if(nodes_2_colour[nid]) {
n.active = true;
selections[nid]=1
// selections[nid]=1
}
else {
n.customAttrs.neighbor = true;
}
}
}
}
console.log('edges_2_colour', edges_2_colour)
for(var eid in edges_2_colour) {
// console.log(eid)
for(var eid in edges_2_colour) {
// at this point all edges are grey b/c greyEverything() was called
let an_edge = TW.partialGraph.graph.edges(eid)
if(!isUndef(an_edge) && !an_edge.hidden){
......@@ -211,6 +239,7 @@ function SelectionEngine() {
// make all color etc changes in renderers depending on flags
an_edge.color = an_edge.customAttrs['true_color'];
an_edge.customAttrs['grey'] = 0;
an_edge.customAttrs['activeEdge'] = 1;
}
}
......@@ -223,6 +252,9 @@ function SelectionEngine() {
// alert("MultipleSelection2=======\nthe_new_sels:" + JSON.stringify(the_new_sels))
// global flag
TW.selectionActive = true
// we send our "gotNodeSet" event
// (signal for plugins that a search-selection was done or a new hand picked selection)
$('#searchinput').trigger({
......@@ -232,37 +264,49 @@ function SelectionEngine() {
});
// console.log("Event [gotNodeSet] sent from Tinaweb MultipleSelection2")
var neighsDict = {}
// TODO REFA this used for bipartite case but needs testing with correct typestring case
if(TW.Relations["1|1"]) {
for(var s in the_new_sels) {
var neighs = TW.Relations["1|1"][the_new_sels[s]];
var bipaNeighs = TW.Relations["1|1"][the_new_sels[s]];
for(var n in neighs) {
if (!neighsDict[neighs[n]])
neighsDict[neighs[n]] = 0;
neighsDict[neighs[n]]++;
if (typeof oppositeSideNeighbors[bipaNeighs[n]] == "undefined")
oppositeSideNeighbors[bipaNeighs[n]] = 0;
oppositeSideNeighbors[bipaNeighs[n]]++;
}
}
}
var oppos = ArraySortByValue(neighsDict, function(a,b){
// debug
// var neiLabls = []
// for (var neiId in sameSideNeighbors) {
// neiLabls.push(TW.Nodes[neiId].label)
// }
// console.log('sameSideNeighbors labels', neiLabls)
// NB doesn't only sort by value but also
// rewrites dict[id]: val
// as array[order]: {key:id, value:val}
var oppos = ArraySortByValue(oppositeSideNeighbors, function(a,b){
return b-a
});
var same = ArraySortByValue(sameSideNeighbors, function(a,b){
return b-a
});
// console.debug('oppos', oppos)
// console.debug('same', same)
//
overNodes=true;
TW.partialGraph.render();
updateLeftPanel( selections , oppos );
for(var n in neighsDict)
delete neighsDict[n]
updateRelatedNodesPanel( selections , same, oppos );
}).index()
};
// REFA tempo expose selectionEngine and methods
// TODO TW.SelInst
var SelInst
......
......@@ -97,14 +97,14 @@ getUrlParam = (function () {
function ArraySortByValue(array, sortFunc){
var tmp = [];
oposMAX=0;
// oposMAX=0;
for (var k in array) {
if (array.hasOwnProperty(k)) {
tmp.push({
key: k,
value: array[k]
});
if((array[k]) > oposMAX) oposMAX= array[k];
// if((array[k]) > oposMAX) oposMAX= array[k];
}
}
......
......@@ -182,9 +182,12 @@ if(RES["OK"]) {
TW.Edges = dicts.edges;
TW.nodeIds = Object.keys(dicts.nodes) // useful for loops
TW.edgeIds = Object.keys(dicts.edges)
TW.selectionActive = false // changes rendering mode
if (the_data.clusters) TW.Clusters = the_data.clusters
TW.nodes1 = dicts.n1;//not used
// TW.nodes1 = dicts.n1;//not used
var catDict = dicts.catDict
// console.log("CategoriesDict: ")
// console.log(catDict)
......
......@@ -19,7 +19,8 @@ function cancelSelection (fromTagCloud) {
// console.log("cancelSelection: edge", e)
if (e) {
e.color = e.customAttrs['grey'] ? e.customAttrs['true_color'] : e.color;
e.customAttrs['grey'] = 0;
e.customAttrs.grey = 0;
e.customAttrs.activeEdge = 0;
}
}
}
......@@ -32,7 +33,7 @@ function cancelSelection (fromTagCloud) {
n.active = false;
// n.color = n.customAttrs['grey'] ? n.customAttrs['true_color'] : n.color;
n.color = n.customAttrs['true_color'];
n.customAttrs['grey'] = 0
n.customAttrs.grey = 0
}
}
......@@ -68,6 +69,9 @@ function cancelSelection (fromTagCloud) {
if(TW.partialGraph.states.slice(-1)[0].level)
LevelButtonDisable(true);
// global flag
TW.selectionActive = false
// finally redraw
TW.partialGraph.render();
}
......@@ -187,12 +191,14 @@ function pushSWClick(arg){
// tag cloud div
function htmlfied_alternodes(elems) {
var oppositesNodes=[]
js1='onclick="graphTagCloudElem(\'';
js2="');\""
frecMAX=elems[0].value
var js1='onclick="graphTagCloudElem(\'';
var js2="');\""
var frecMAX=elems[0].value
for(var i in elems){
id=elems[i].key
frec=elems[i].value
var id=elems[i].key
var frec=elems[i].value
var fontSize
var htmlfied_alternode
if(frecMAX==1) fontSize=desirableTagCloudFont_MIN;
else {
fontSize=
......@@ -201,8 +207,7 @@ function htmlfied_alternodes(elems) {
((desirableTagCloudFont_MAX-desirableTagCloudFont_MIN)/(frecMAX-1));
}
if(!isUndef(TW.Nodes[id])){
// js1 js2
// onclick="graphTagCloudElem(' ');
htmlfied_alternode = '<span class="tagcloud-item" style="font-size:'+fontSize+'px;" '+js1+id+js2+'>'+ TW.Nodes[id].label+ '</span>';
oppositesNodes.push(htmlfied_alternode)
}
......@@ -213,7 +218,9 @@ function htmlfied_alternodes(elems) {
function manualForceLabel(nodeid, active, justHover) {
// console.log("manual|"+nodeid+"|"+active)
var nd = TW.partialGraph.graph.nodes(nodeid)
nd.active=active;
// TODO harmonize with other status => bien re-distinguer neighbor et active
// nd.active=active;
// console.log('justHover', justHover)
// var t0, t1
......@@ -261,22 +268,22 @@ function clearHover() {
)
}
function htmlfied_samenodes(elems) {
var sameNodes=[]
js1=' onmouseover="manualForceLabel(this.id,true, true);" ';
js2=' onmouseout="manualForceLabel(this.id,true, true);" ';
if(elems.length>0) {
var A = getVisibleNodes()
for (var a in A){
n = A[a]
if(!n.active && n.color.charAt(0)=="#" ) {
sameNodes.push('<li onmouseover="manualForceLabel(\''+n.id+'\',true, true)" onmouseout="manualForceLabel(\''+n.id+'\',false, true)" ><a>'+ n.label+ '</a></li>')
}
}
}
return sameNodes
}
// TODO rm ? function doesn't make sense, probably replaced by htmlfied_tagcloud
// function htmlfied_samenodes(elems) {
// var sameNodes=[]
// js1=' onmouseover="manualForceLabel(this.id,true, true);" ';
// js2=' onmouseout="manualForceLabel(this.id,true, true);" ';
// if(elems.length>0) {
// var A = getVisibleNodes()
// for (var a in A){
// n = A[a]
// if(!n.active && n.color.charAt(0)=="#" ) {
// sameNodes.push('<li onmouseover="manualForceLabel(\''+n.id+'\',true, true)" onmouseout="manualForceLabel(\''+n.id+'\',false, true)" ><a>'+ n.label+ '</a></li>')
// }
// }
// }
// return sameNodes
// }
// nodes information div
function htmlfied_nodesatts(elems){
......@@ -344,11 +351,15 @@ function htmlfied_tagcloud(elems , limit) {
let id=elems[i].key
let frec=elems[i].value
if(frecMAX > 1) {
let fontSize=
fontSize=
desirableTagCloudFont_MIN+
(frec-1)*
((desirableTagCloudFont_MAX-desirableTagCloudFont_MIN)/(frecMAX-1));
}
// debug
// console.log('htmlfied_tagcloud (',id, TW.Nodes[id].label,') freq',frec,' fontSize', fontSize)
if(!isUndef(TW.Nodes[id])){
var jspart = ' onclick="manualSelectNode(\''+id+'\')" onmouseover="manualForceLabel(\''+id+'\',true, true)" onmouseout="manualForceLabel(\''+id+'\',false, true)"'
let htmlfied_alternode = '<span class="tagcloud-item" style="font-size:'+fontSize+'px;" '+jspart+'>'+ TW.Nodes[id].label+ '</span>';
......@@ -360,7 +371,23 @@ function htmlfied_tagcloud(elems , limit) {
//missing: getTopPapers for both node types
//considering complete graphs case! <= maybe i should mv it
function updateLeftPanel( sels , oppos ) {
function updateRelatedNodesPanel( sels , same, oppos ) {
// debug
// neiLabls = []
// for (var l in same) {
// var neiId = same[l].key
// if (TW.Nodes[neiId]) {
//
// neiLabls.push(TW.Nodes[neiId].label)
// }
// else {
// console.warn("missing entry for neiId", neiId)
// }
// }
// console.log("updateRelatedNodesPanel, same:",neiLabls)
var namesDIV=''
var alterNodesDIV=''
var informationDIV=''
......@@ -379,19 +406,8 @@ function updateLeftPanel( sels , oppos ) {
var sameNodesDIV = "";
if(getNodeIDs(sels).length>0) {
var temp_voisinage = {}
var A = getVisibleNodes()
for (var a in A){
var n = A[a]
if(!n.active && n.color.charAt(0)=="#" ) {
temp_voisinage[n.id] = Math.round(TW.Nodes[n.id].size)
}
}
var voisinage = ArraySortByValue(temp_voisinage, function(a,b){
return b-a
});
sameNodesDIV+='<div id="sameNodes">';//tagcloud
var tagcloud_opposite_neigh = htmlfied_tagcloud( voisinage , TW.tagcloud_limit)
var tagcloud_opposite_neigh = htmlfied_tagcloud( same , TW.tagcloud_limit)
sameNodesDIV+= (tagcloud_opposite_neigh!=false) ? tagcloud_opposite_neigh.join("\n") : "No related terms.";
sameNodesDIV+= '</div>';
}
......@@ -547,18 +563,23 @@ function graphTagCloudElem(nodes) {
}
// /!\ £TODO change only *flags* here, and then
// make all color etc changes in renderers depending on flags
function greyEverything(){
// edges greyish color for unselected, when we have a selection
// case default: color is precomputed as node true_color + alpha .5
// cases when coloredBy (ex: centrality): color must be recomputed here
function greyEverything(notDefaultColors){
for(let j=0 ; j<TW.nNodes ; j++){
let n = TW.partialGraph.graph.nodes(TW.nodeIds[j])
if (n && !n.hidden && !n.customAttrs.grey) {
n.customAttrs.true_color = n.color
// TODO check if no simpler strategy than reinvoke hex2rga each time
// n.color = "rgba("+hex2rga(n.color)+",0.5)"
n.color = "rgba(15,15,15,0.5)"
n.customAttrs['grey'] = 1
n.customAttrs.true_color = n.color
// normal case handled by node renderers
// will see the n.customAttrs.grey flag => use n.customAttrs.defgrey_color
// special case after a coloredBy or clustersBy
if (notDefaultColors)
n.color = "rgba("+hex2rga(n.color)+",0.5)"
}
}
......@@ -566,9 +587,8 @@ function greyEverything(){
for(let i=0;i<TW.nEdges;i++){
let e = TW.partialGraph.graph.edges(TW.edgeIds[i])
if (e && !e.hidden && !e.customAttrs.grey) {
e.customAttrs.true_color = e.color
e.color = TW.edgeGreyColor
e.customAttrs.grey = 1
e.customAttrs.true_color = e.color
}
}
}
......@@ -576,6 +596,7 @@ function greyEverything(){
}
// new sigma.js: TODO change logic (the reverse of greyEverything is done by redraw for the colors, and cancelSelection for the flags...)
// but this could be used for colorsBy menu
// function graphResetColor(){
// nds = TW.partialGraph.graph.nodes().filter(function(x) {
// return !x['hidden'];
......
......@@ -24,9 +24,20 @@ SigmaUtils = function () {
type : n.type,
// new setup (TODO rm the old at TinaWebJS nodes_2_colour)
customAttrs : {
grey: 0,
true_color : n.color
}
grey: false,
true_color : n.color,
defgrey_color : "rgba("+hex2rga(n.color)+",.4)"
},
// £TODO gather all flags like this
// customFlags : {
// // status flags
// grey: false,
// active: false,
// hidden: false,
// // forceLabel: false,
// neighbour: false,
// }
}
if(n.shape) node.shape = n.shape;
// console.log("FillGraph, created new node:", node)
......@@ -50,6 +61,8 @@ SigmaUtils = function () {
let e = TW.Edges[s+";"+t]
if(e) {
if(e.source != e.target) {
var computedColorInfo = sigmaTools.edgeColor(e.source, e.target, nodes)
var edge = {
// sigma mandatory properties
......@@ -58,16 +71,17 @@ SigmaUtils = function () {
source : e.source,
target : e.target,
weight : e.weight,
// size : e.weight, // REFA s/weight/size/ ?
size : e.weight, // REFA s/weight/size/ ?
color : sigmaTools.edgeColor(e.source, e.target, nodes),
color : computedColorInfo.res,
hidden : false,
// twjs additional properties
type : e.type,
customAttrs : {
grey: 0,
true_color : n.color
true_color : computedColorInfo.res,
rgb : computedColorInfo.rgb_array
}
}
......@@ -132,7 +146,11 @@ SigmaUtils = function () {
fontSize + 'px ' + (settings('hoverFont') || settings('font'));
context.beginPath();
context.fillStyle = "#F7E521"; // yellow
if (TW.selectedColor == "node")
context.fillStyle = node.color; // node's
else
context.fillStyle = "#F7E521"; // yellow
if (node.label && settings('labelHoverShadow')) {
context.shadowOffsetX = 0;
......@@ -196,29 +214,37 @@ SigmaUtils = function () {
};
// source: github.com/jacomyal/sigma.js/commit/25e2153
// POSS: modify to incorporate mix colors (repaintEdges)
// + boosting edges with property edge.customAttrs.activeEdge
this.twRender.canvas.edges.curve = function(edge, source, target, context, settings) {
var color = edge.color,
prefix = settings('prefix') || '',
edgeColor = settings('edgeColor'),
defaultNodeColor = settings('defaultNodeColor'),
defaultEdgeColor = settings('defaultEdgeColor');
if (!color)
switch (edgeColor) {
case 'source':
color = source.color || defaultNodeColor;
break;
case 'target':
color = target.color || defaultNodeColor;
break;
default:
color = defaultEdgeColor;
break;
}
var color, size,
prefix = settings('prefix') || ''
//debug
// console.warn("rendering edge", edge)
var rgb = edge.customAttrs.rgb
var defSize = edge[prefix + 'size'] || 1
if (edge.customAttrs.activeEdge) {
size = defSize * 1.5
// color with less opacity
// cf. sigmaTools.edgeColor
color = 'rgba('+rgb.join()+',.7)'
}
else if (edge.customAttrs.grey) {
color = TW.edgeGreyColor
size = 1
}
else {
// color = "rgba( "+rgb.join()+" , "+TW.edgeDefaultOpacity+")";
color = edge.customAttrs.true_color
size = defSize
}
context.strokeStyle = color;
context.lineWidth = edge[prefix + 'size'] || 1;
context.lineWidth = size ;
context.beginPath();
context.moveTo(
source[prefix + 'x'],
......@@ -235,18 +261,44 @@ SigmaUtils = function () {
context.stroke();
};
// node rendering with borders
// node rendering with borders and sensitive to current selection mode
this.twRender.canvas.nodes.withBorders = function(node, context, settings) {
var prefix = settings('prefix') || '';
let X = node[prefix + 'x']
let Y = node[prefix + 'y']
var borderSize = node[prefix + 'size'] + settings('twNodeRendBorderSize')
var borderColor = settings('twNodeRendBorderColor') || "#000"
var nodeSize = node[prefix + 'size']
var nodeColor = node.color || settings('defaultNodeColor')
// mode variants
if (TW.selectionActive) {
// passive nodes should blend in the grey of TW.edgeGreyColor
if (node.customAttrs.grey) {
nodeColor = node.customAttrs.defgrey_color
borderColor = TW.nodesGreyBorderColor
// cf settings_explorerjs, defgrey_color and greyEverything()
}
// neighbor nodes should be more visible
else if(node.customAttrs.neighbor) {
// borderColor = "rgba(220, 220, 220, 0.7)"
nodeSize *= 1.4
borderSize *= 1.4
}
else if(node.active) {
borderColor = null
// the selected nodes: fill not important because label+background overlay
}
}
// actual drawing
if (settings('twNodeRendBorderSize') > 0) {
context.fillStyle = borderColor
context.beginPath();
context.fillStyle = settings('twNodeRendBorderColor') || "#000"
context.arc(
X,Y,
node[prefix + 'size'] + settings('twNodeRendBorderSize'),
borderSize,
0,
Math.PI * 2,
true
......@@ -255,11 +307,11 @@ SigmaUtils = function () {
context.fill();
}
context.fillStyle = node.color || settings('defaultNodeColor');
context.fillStyle = nodeColor;
context.beginPath();
context.arc(
X,Y,
node[prefix + 'size'],
nodeSize,
0,
Math.PI * 2,
true
......@@ -675,7 +727,11 @@ function repaintEdges() {
var r = (a[0] + b[0]) >> 1;
var g = (a[1] + b[1]) >> 1;
var b = (a[2] + b[2]) >> 1;
TW.partialGraph.graph.edges(e_id).color = "rgba("+[r,g,b].join(",")+",0.5)";
// also keep components array (useful if we change opacity when selected)
TW.partialGraph.graph.edges(e_id).customAttrs.rgb = [r,g,b]
}
}
......
......@@ -20,6 +20,7 @@ sigmaTools = (function(stools) {
'0123456789ABCDEF'.charAt(n % 16);
};
// TODO check duplicate functionalities with repaintEdges
stools.edgeColor = function(src_id, tgt_id, nodes) {
//edge color will be the combination of the 2 node colors
var a = nodes[src_id]['color'];
......@@ -46,7 +47,7 @@ sigmaTools = (function(stools) {
// var color = '#'+sigma.tools.rgbToHex(parseFloat(r),parseFloat(g),parseFloat(b))
var color = "rgba( "+r+", "+g+" , "+b+" , "+TW.edgeDefaultOpacity+")";
return color
return {'res':color, 'rgb_array':[r,g,b]}
}
return stools
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment