Pergunta

I am trying to use InfoVis / JIT to render a force directed graph visualizing a network. I am a newbie to both java script and JIT. I have created my own custom node types using following code in my js file, which lets me display my image on the node.

$jit.ForceDirected.Plot.NodeTypes.implement({
    'icon1': { 
         'render': function(node, canvas){ 
                    var ctx = canvas.getCtx(); 
                    var img = new Image(); 
                    img.src='magnify.png'; 
                    var pos = node.pos.getc(true); 
                    img.onload = function() { 
                            ctx.drawImage(img, pos.x, pos.y); 
                    }; 

            }, 
            'contains': function(node,pos){ 
                    var npos = node.pos.getc(true); 
                    dim = node.getData('dim'); 
                    return this.nodeHelper.circle.contains(npos, pos, dim);
                    //return this.nodeHelper.square.contains(npos, pos, dim); 
            } 
     }

I am assigning this custom node type to the node using "$type": "icon1" in the json data object. I do get image on the node, but the problem is that I am not able to hide it when required. I am able to hide the in-built node types like circle,square etc. using following code.

 node.setData('alpha', 0);
 node.eachAdjacency(function(adj) {
     adj.setData('alpha', 0);
 });
 fd.fx.animate({
     modes: ['node-property:alpha',
          'edge-property:alpha'],
     duration: 2000
 });

But the same code does not work for custom nodes. Hence I tried to temporarily change the type of node to the built-in "circle" type, hid it and then re-setted the type of node to its original i.e. my custom node, icon1.

function hideNode( ){
  var typeOfNode = node.getData('type');
  node.setData( 'type','circle');
  node.setData('alpha', 0);
  node.eachAdjacency(function(adj) {
       adj.setData('alpha', 0);
  }); 
   fd.fx.animate({
          modes: ['node-property:alpha',
                  'edge-property:alpha'],
          duration: 2000
   });

   node.setData('type',typeOfNode );    
 }

I think this should work but the custom image comes back in a while on the canvas. If I don't reset the type of node to its original i.e. in the above code and comment out the following statement and call hide function, then the node gets hidden.

  node.setData('type',typeOfNode );

I am not able to figure out how by only setting a node's type to some custom type, the node is being rendered. Any help with this question will be appreciated.

I need to re-set the node's type to its original because I want the node to be restored when required by calling unhide function. If I don't reset node's type to the original then it would be rendered as a circle when restored.

I have gone through the API and the google group for JIT but couldn't find an answer. Can anyone help?

Foi útil?

Solução

Here's a look at a snippet from the Plot's plotNode function:

var alpha = node.getData('alpha'),
    ctx = canvas.getCtx();
ctx.save();
ctx.globalAlpha = alpha;

// snip

this.nodeTypes[f].render.call(this, node, canvas, animating);
ctx.restore();

As you can see, the node's alpha value is applied to the canvas immediately before the node's render function is called. After rendering the node, the canvas is restored to the previous state.

The issue here is that your custom node's render function does not render the node synchronously, and the canvas state is getting restored prior to the call to drawImage. So, you can do one of two things:

1) Preload and cache your image (preferred approach, as this will also prevent image flickering and help with performance):

// preload image
var magnifyImg = new Image();
magnifyImg.src = 'magnify.png';

// 'icon1' node render function:
'render': function(node, canvas){ 
    var ctx = canvas.getCtx(); 
    var pos = node.pos.getc(true); 
    ctx.drawImage(magnifyImg, pos.x, pos.y); 
}

or 2) save the canvas state, reapply the alpha, and then restore the canvas state after drawing the image in your onload handler:

// 'icon1' node render function:
'render': function(node, canvas){ 
    var ctx = canvas.getCtx(); 
    var img = new Image(); 
    img.src='magnify.png'; 
    var pos = node.pos.getc(true); 
    img.onload = function() {
        ctx.save(); // save current canvas state
        ctx.globalAlpha = node.getData('alpha'); // apply node alpha
        ctx.drawImage(img, pos.x, pos.y); // draw image
        ctx.restore(); // revert to previous canvas state
    };
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top