在D3的上下文菜单中获取节点详细信息 [英] Getting the node details in the context menu in D3

查看:117
本文介绍了在D3的上下文菜单中获取节点详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图右键单击它并调用contextmenu函数来获取节点详细信息(id属性).我可以使用var self = d3.select(this);获取节点对象,但无法计算出 节点的id属性(尽管我可以在控制台日志中看到它)

I am trying to get the node details (id attribute) when it is right clicked and the contextmenu function is called. I am able to get the node object using var self = d3.select(this); but I am not able to work out the id attribute of the node (i can see it in the console log though)

我计划在获得node.id

JSFiddle

var circle = svg.append("g").selectAll("circle") .data(force.nodes())
  .enter().append("circle").attr("r", 6) .call(force.drag)
  .on('contextmenu', function(){ 
     d3.event.preventDefault();
     var self = d3.select(this);
     console.log(self);
     var n1=(self[0])[0];
     console.log(n1);
     menu(d3.mouse(svg.node())[0], d3.mouse(svg.node())[1]);
});

推荐答案

您可以将数据作为在contextmenu事件上调用的函数的参数传递:

You can pass the datum as a parameter of the function called on the contextmenu event:

.on('contextmenu', function(d) { ... }

允许您在函数中获取id:

console.log(d.id);

.node {
  fill: #000;
}

.cursor {
  fill: green;
  stroke: brown;
  pointer-events: none;
}


.node text {
  pointer-events: none;
  font: 10px sans-serif;
}

path.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}



.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

#licensing {
  fill: green;
}

.link.licensing {
  stroke: green;
}

.link.resolved {
  stroke-dasharray: 0,2 1;
}

circle {
  fill: green;
  stroke: red;
  stroke-width: 1.5px;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
  text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}

<script src="https://d3js.org/d3.v3.min.js"></script>
    <script>
    var width = 500,    height = 300;
    var links = [{source:"simulator",target:"monitor" ,type:"resolved"} , {source:"web",target:"monitor" ,type:"resolved"} ];

 
 
    var nodes = [ {"id":"monitor", "grp":"system"}, {"id":"simulator", "grp":"system"}, {id:"web", grp:"client"}];


      function reset() {
        }

 
function contextMenu() {
    var height,
        width, 
        margin = 0.1, // fraction of width
        items = [], 
        rescale = false, 
        style = {
            'rect': {
                'mouseout': {
                    'fill': 'rgb(244,244,244)', 
                    'stroke': 'white', 
                    'stroke-width': '1px'
                }, 
                'mouseover': {
                    'fill': 'rgb(200,200,200)'
                }
            }, 
            'text': {
                'fill': 'steelblue', 
                'font-size': '13'
            }
        }; 
    
    function menu(x, y) {
        d3.select('.context-menu').remove();
        scaleItems();

        // Draw the menu
        d3.select('svg')
            .append('g').attr('class', 'context-menu')
            .selectAll('tmp')
            .data(items).enter()
            .append('g').attr('class', 'menu-entry')
            .style({'cursor': 'pointer'})
            .on('mouseover', function(){ 
                d3.select(this).select('rect').style(style.rect.mouseover) })
            .on('mouseout', function(){ 
                d3.select(this).select('rect').style(style.rect.mouseout) });
        
        d3.selectAll('.menu-entry')
            .append('rect')
            .attr('x', x)
            .attr('y', function(d, i){ return y + (i * height); })
            .attr('width', width)
            .attr('height', height)
            .style(style.rect.mouseout);
        
        d3.selectAll('.menu-entry')
            .append('text')
            .text(function(d){ return d; })
            .attr('x', x)
            .attr('y', function(d, i){ return y + (i * height); })
            .attr('dy', height - margin / 2)
            .attr('dx', margin)
            .style(style.text);

        // Other interactions
        d3.select('body')
            .on('click', function() {
                d3.select('.context-menu').remove();
            });

    }
    
    menu.items = function(e) {
        if (!arguments.length) return items;
        for (i in arguments) items.push(arguments[i]);
        rescale = true;
        return menu;
    }

    // Automatically set width, height, and margin;
    function scaleItems() {
        if (rescale) {
            d3.select('svg').selectAll('tmp')
                .data(items).enter()
                .append('text')
                .text(function(d){ return d; })
                .style(style.text)
                .attr('x', -1000)
                .attr('y', -1000)
                .attr('class', 'tmp');
            var z = d3.selectAll('.tmp')[0]
                      .map(function(x){ return x.getBBox(); });
            width = d3.max(z.map(function(x){ return x.width; }));
            margin = margin * width;
            width =  width + 2 * margin;
            height = d3.max(z.map(function(x){ return x.height + margin / 2; }));
            
            // cleanup
            d3.selectAll('.tmp').remove();
            rescale = false;
        }
    }

    return menu;
}


var width = 400,
  height = 200,
    radius = 8;


var map = {}
nodes.forEach(function(d,i){
  map[d.id] = i;
})

links.forEach(function(d) {
  d.source = map[d.source];
  d.target = map[d.target];
})

    var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(links)
    .size([width, height])
    .linkDistance(50)
    .charge(-200)
    .on("tick", tick)
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);


// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
    .data(["suit", "licensing", "resolved"])
  .enter().append("marker")
    .attr("id", function(d) { return d; })
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)
    .attr("refY", -1.5)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
  .append("path")
    .attr("d", "M0,-5L10,0L0,5");

var path = svg.append("g").selectAll("path")
    .data(force.links())
  .enter().append("path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

var menu = contextMenu().items('first item', 'second option', 'whatever, man');

var circle = svg.append("g").selectAll("circle")
    .data(force.nodes())
  .enter().append("circle")
    .attr("r", 6)
    .call(force.drag)
    .on('contextmenu', function(d){ 
        d3.event.preventDefault();
        
        var self = d3.select(this);
        var n1=(self[0])[0];
        console.log(d.id);
        
        menu(d3.mouse(svg.node())[0], d3.mouse(svg.node())[1]);
    });

var text = svg.append("g").selectAll("text")
    .data(force.nodes())
  .enter().append("text")
    .attr("x", 8)
    .attr("y", ".31em")
    .text(function(d) { return d.id; });

var node = svg.selectAll(".node"),
  link = svg.selectAll(".link");

  
function mousedownNode(d, i) {
  nodes.splice(i, 1);
  links = links.filter(function(l) {
    return l.source !== d && l.target !== d;
  });
  d3.event.stopPropagation();

  refresh();
}
  
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
  path.attr("d", linkArc);
  circle.attr("transform", transform);
  text.attr("transform", transform);
}

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}



    </script>

这篇关于在D3的上下文菜单中获取节点详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆