2016-03-23 3 views
0

Я строю ориентированный граф, где на hover событие Я хочу выделить соответствующие узлы, ссылки и соседи. Все идет хорошо, пока я не добавлю стрелки к ссылкам.D3 force layout hover on arrow

Я не могу тренироваться, как выделить стрелки, а также ссылки.

Любая помощь приветствуется.

jsfiddle: https://jsfiddle.net/dkroaefw/3/

код:

graph = { 
    "nodes": [{ 
    "name": "a" 
    }, { 
    "name": "b" 
    }, { 
    "name": "c" 
    }, { 
    "name": "d" 
    }, { 
    "name": "e" 
    }, { 
    "name": "f" 
    }, { 
    "name": "g" 
    }], 
    "links": [{ 
    "source": 0, 
    "target": 1, 
    "value" :1 
    }, { 
    "source": 1, 
    "target": 2, 
    "value" :1 
    }, { 
    "source": 1, 
    "target": 3, 
    "value" :1 
    }, { 
    "source": 0, 
    "target": 4, 
    "value" :1 
    }, { 
    "source": 4, 
    "target": 5, 
    "value" :1 
    }, { 
    "source": 4, 
    "target": 6, 
    "value" :1 
    }] 
} 

var linkedByIndex = {}; 
graph.links.forEach(function(d) { 
    linkedByIndex[d.source + "," + d.target] = true; 
}); 

function isConnected(a, b) { 
    return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index; 
} 

function hasConnections(a) { 
    for (var property in linkedByIndex) { 
    s = property.split(","); 
    if ((s[0] == a.index || s[1] == a.index) && linkedByIndex[property]) 
     return true; 
    } 
    return false; 
} 

var width = 500 
    height = 400 

var force = d3.layout.force() 
    .nodes(graph.nodes) 
    .links(graph.links) 
    .charge(-50) 
    .linkDistance(50) 
    .size([width, height]) 
    .start(); 

// Zoom definition 
var zoom = d3.behavior.zoom() 
    .scaleExtent([1, 10]) 
    .on("zoom", zoomed); 

function zoomed() { 
    container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
} 

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


var rect = svg.append("rect") 
    .attr("width", width) 
    .attr("height", height) 
    .style("fill", "none") 
    .style("pointer-events", "all") 
    .call(zoom); 

var container = svg.append("g"); 

// build the arrow. 
var arrow = container.append("svg:defs") 
    .selectAll("marker") 
    .data(["end"]) // Different link/path types can be defined here 
    .enter().append("svg:marker") // This section adds in the arrows 
    .attr("class", "arrow") 
    .attr("id", String) 
    .attr("viewBox", "0 -5 10 10") 
    .attr("refX", 20) 
    .attr("markerWidth", 6) 
    .attr("markerHeight", 6) 
    .attr("orient", "auto") 
    .append("svg:path") 
    .attr("d", "M0,-5L10,0L0,5"); 

var link = container.append("g") 
    .attr("class", "links") 
    .selectAll(".links") 
    .data(force.links()) 
    .enter().append("line") 
    .attr("class", "link") 
    .attr("marker-end", "url(#end)"); 

var node = container.append("g") 
    .attr("class", "nodes") 
    .selectAll(".node") 
    .data(force.nodes()) 
    .enter().append("g") 
    .attr("class", "node") 
    .attr("cx", function(d) { 
    return d.x; 
    }) 
    .attr("cy", function(d) { 
    return d.y; 
    }) 
    .on("mouseover", mouseover) 
    .on("mouseout", mouseout) 
    .call(force.drag); 

node.append("circle") 
    .attr("r", 5); 

node.append("text") 
    .attr("class", "text") 
    .attr("x", 12) 
    .attr("dy", ".35em") 
    .text('') 

force.on("tick", function(f) { 

    link 
    .attr("x1", function(d) { 
     return d.source.x; 
    }) 
    .attr("y1", function(d) { 
     return d.source.y; 
    }) 
    .attr("x2", function(d) { 
     return d.target.x; 
    }) 
    .attr("y2", function(d) { 
     return d.target.y; 
    }); 
    node.attr("transform", function(d) { 
    return "translate(" + d.x + "," + d.y + ")"; 
    }); 
}); 

function mouseover(d) { 
    d3.select(this).select("circle").transition() 
    .duration(750) 
    .attr("r", 8); 
    set_highlight(d); 
} 

function mouseout(d) { 
    d3.select(this).select("circle").transition() 
    .duration(750) 
    .attr("r", 5); 
    exit_highlight(d) 
} 

function set_highlight(d) { 
    node.select("text").text(function(o) { 
    return isConnected(d, o) ? o.name : ""; 
    }) 
    node.attr("class", function(o) { 
    return isConnected(d, o) ? "node-active" : "node"; 
    }); 
    link.attr("class", function(o) { 
    return o.source.index == d.index || o.target.index == d.index ? "link-active" : "link"; 
    }); 
} 

function exit_highlight(d) { 
    node.attr("class", "node"); 
    link.attr("class", "link"); 
    node.select("text").text("") 
} 

ответ

3

Итак, есть 2 вещи, которые вы должны принять во внимание IMHO:

  1. Так как вы хотите, чтобы выделить только некоторые стрелки, вы необходимо будет определить два маркера и переключить маркеры для ссылок.
  2. Вы также захотите переключить стиль ссылки.

Так в основном - проверить this fiddle, чтобы увидеть все изменения:

var arrows = defs 
    .selectAll("marker") 
    // let's add two markers: one for unhovered links and one for hovered links. 
    .data(["end", "end-active"]) // Different link/path types can be defined here 
    .enter().append("svg:marker") // This section adds in the arrows 
    .attr("id", String) 
    .attr("viewBox", "0 -5 10 10") 
    .attr("refX", 20) 
    .attr("markerWidth", 6) 
    .attr("markerHeight", 6) 
    .attr("orient", "auto") 
    .append("svg:path") 
    .attr("d", "M0,-5L10,0L0,5"); 

    //define the classes for each of the markers. 
    defs.select("#end").attr("class", "arrow"); 
    defs.select("#end-active").attr("class", "arrow-active"); 
//... 
// then further down in function set_highlight and exit highlight: 
function set_highlight(d) { 
    node.select("text").text(function(o) { 
    return isConnected(d, o) ? o.name : ""; 
    }) 
    node.attr("class", function(o) { 
    return isConnected(d, o) ? "node-active" : "node"; 
    }); 
    link.attr("marker-end", function(o) { 
    return o.source.index == d.index || o.target.index == d.index ? "url(#end-active)" : "url(#end)"; 
    }); 
    link.attr("class", function(o) { 
    return o.source.index == d.index || o.target.index == d.index ? "link-active" : "link"; 
    }); 
} 



function exit_highlight(d) { 
    node.attr("class", "node"); 
    link.attr("class", "link"); 
    link.attr("marker-end", "url(#end)"); 
    node.select("text").text("") 
} 

EDIT: если вы хотите использовать некоторые из кода можно добавить следующее:

// inside the set_highlight function 
    link.attr("marker-end", function(o) { 
     return isLinkForNode(d, o) ? "url(#end-active)" : "url(#end)"; 
    }); 
    link.attr("class", function(o) { 
     return isLinkForNode(d, o) ? "link-active" : "link"; 
    }); 


function isLinkForNode(node, link) { 
    return link.source.index == node.index || link.target.index == node.index; 
} 
+0

Спасибо много, он работал как шарм. Извините за наивный вопрос. Я новичок в javascript/d3. Ура! – TheDimLebowski

+0

Эй! нет такого понятия. В любой момент :) – Rick

Смежные вопросы