Как скрыть и восстановить пользовательские узлы в силовом ориентированном графе InfoVis/JIT?

Я пытаюсь использовать InfoVis / JIT для визуализации силового графа, визуализирующего сеть. Я новичок в Java-сценарии и JIT. Я создал свои собственные типы узлов, используя следующий код в моем файле js, который позволяет мне отображать мое изображение на узле.

$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); 
            } 
     }

Я назначаю этот пользовательский тип узла узлу, используя "$type": "icon1" в объекте данных json. Я получаю изображение на узле, но проблема в том, что я не могу его скрыть при необходимости. Я могу скрыть встроенные типы узлов, такие как круг, квадрат и т. Д., Используя следующий код.

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

Но тот же код не работает для пользовательских узлов. Поэтому я попытался временно изменить тип узла на встроенный тип "круга", спрятал его, а затем заново установил тип узла на его исходный, т.е. мой пользовательский узел, 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 );    
 }

Я думаю, что это должно работать, но пользовательское изображение возвращается на холсте через некоторое время. Если я не сбрасываю тип узла до его первоначального значения, то есть в приведенном выше коде, закомментирую следующее утверждение и вызываю функцию hide, то узел будет скрыт.

  node.setData('type',typeOfNode );

Я не могу понять, как, только устанавливая тип узла в некоторый пользовательский тип, узел рендерится. Любая помощь с этим вопросом будет оценена.

Мне нужно заново установить тип узла в исходное состояние, потому что я хочу, чтобы узел восстанавливался при необходимости путем вызова функции отображения. Если я не сбрасываю тип узла на исходный, то при восстановлении он будет отображаться как круг.

Я прошел через API и группу Google для JIT, но не смог найти ответ. Кто-нибудь может помочь?

1 ответ

Решение

Вот взгляд на фрагмент из функции plotNode в Plot:

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();

Как вы можете видеть, альфа-значение узла применяется к холсту непосредственно перед вызовом функции рендеринга узла. После рендеринга узла холст возвращается в предыдущее состояние.

Проблема в том, что ваш пользовательский узел render функция не выполняет визуализацию узла синхронно, и состояние холста восстанавливается до вызова drawImage, Итак, вы можете сделать одну из двух вещей:

1) Предварительная загрузка и кэширование вашего изображения (предпочтительный подход, так как это также предотвратит мерцание изображения и повысит производительность):

// 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); 
}

или 2) сохранить состояние холста, повторно применить альфа, а затем восстановить состояние холста после рисования изображения в вашем onload обработчик:

// '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
    };
}
Другие вопросы по тегам