处理Mouseevent的更有效方法

时间:2016-05-25 17:34:25

标签: javascript angularjs d3.js mouseevent

我已经实现了一个sankey图表,能够跟踪图表中的节点路径。但是,由于功能性,用户必须mouseenter一个节点突出显示并删除节点路径的突出显示。什么是在mouseenter上突出显示节点路径然后删除该突出显示(通过不透明度更改)mouseout的好方法?顺便说一下,我试图调用该函数使用mouseentermouseout的组合,但似乎没有解决问题。这是我的代码:

function highlightNodeLinks(node, i) {

    var remainingNodes = [],
        nextNodes = [],
        strokeOpacity = 0,
        traverse;

    if ( d3.select(this).attr('data-hover') === '1' ) {
      d3.select(this).attr('data-hover', '0');
      strokeOpacity = 0.2;
    } else {
      d3.select(this).attr('data-hover', '1');
      strokeOpacity = 0.5;
    }

    traverse = [{
      linkType : 'sourceLinks',
      nodeType : 'target'
    }, {
      linkType : 'targetLinks',
      nodeType : 'source'
    }];

    traverse.forEach(function (step) {
      node[step.linkType].forEach(function (link) {
        remainingNodes.push(link[step.nodeType]);
        highlightLink(link.id, strokeOpacity);
      });

      while (remainingNodes.length) {
        nextNodes = [];
        remainingNodes.forEach(function (node) {
          node[step.linkType].forEach(function (link) {
            nextNodes.push(link[step.nodeType]);
            highlightLink(link.id, strokeOpacity);
          });
        });
        remainingNodes = nextNodes;
      }
    });
  }

  function highlightLink(id, opacity) {
    d3.select('#link-' + id).style('stroke-opacity', opacity);
  }

以下是它的调用方式:

  .on('mouseover', highlightNodeLinks)

一如既往地感谢任何考虑和建议。

2 个答案:

答案 0 :(得分:2)

分两步:首先进行预处理,以便每个节点“知道”必须在鼠标悬停时突出显示的链接集。这对于内存来说很重要(对于非常大的图表,它不会扩展),但应该更具响应性

//call this once after loading the data and first drawing of the links
node.forEach(function(n) {

 linkIds= []; //add this field to each node

 traverse.forEach(function (step) {
   node[step.linkType].forEach(function (link) {
     remainingNodes.push(link[step.nodeType]);
     linkIds.push(link.id);
   });

   while (remainingNodes.length) {
    nextNodes = [];
     remainingNodes.forEach(function (node) {
      node[step.linkType].forEach(function (link) {
         nextNodes.push(link[step.nodeType]);
         linkIds(link.id);
       });
     });
     remainingNodes = nextNodes;
   }

   //add the list of links to a new  field in the node
   //& transform already ids into d3 selections
   n.linksToHighlight = linkIds.map(function(id) {return d3.select("link-"+id)})
 });

然后,突出显示代码:

function highlighter(ratio) {
  return function(node) {
     node.linksToHighlight.forEach(function (s) {s.style("stroke-opacity",ratio})
  }
}


[select nodes]
 .on('mouseenter', highlighter(0.5) )     
 .on('mouseout', highlighter(1) )

答案 1 :(得分:1)

我刚刚使用d3实现了一个指令,我想你会找到你要找的例子,你可以查看github上的代码https://github.com/amgadfahmi/angular-bubbletree