Last active
May 25, 2023 04:59
-
-
Save pkerpedjiev/0389e39fad95e1cf29ce to your computer and use it in GitHub Desktop.
Revisions
-
pkerpedjiev renamed this gist
Feb 8, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
pkerpedjiev revised this gist
Feb 8, 2015 . 2 changed files with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ . -
pkerpedjiev revised this gist
Feb 8, 2015 . 2 changed files with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ A variation of the force directed graph which allows selection of multiple nodes. LoadingSorry, something went wrong. Reload?Sorry, we cannot display this file.Sorry, this file is invalid so it cannot be displayed. -
Peter Kerpedjiev revised this gist
Feb 8, 2015 . 2 changed files with 255 additions and 189 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,5 +23,7 @@ </style> <body> <div align='center' id="d3_selectable_force_directed_graph"></div> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="plot.js"></script> <script>selectableForceDirectedGraph();</script> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,232 +1,296 @@ function selectableForceDirectedGraph() { var width = 960, height = 500, shiftKey, ctrlKey; var nodeGraph = null; var xScale = d3.scale.linear() .domain([0,width]).range([0,width]); var yScale = d3.scale.linear() .domain([0,height]).range([0, height]); var svg = d3.select("#d3_selectable_force_directed_graph") .attr("tabindex", 1) .on("keydown.brush", keydown) .on("keyup.brush", keyup) .each(function() { this.focus(); }) .append("svg") .attr("width", width) .attr("height", height); var zoomer = d3.behavior.zoom(). scaleExtent([0.1,10]). x(xScale). y(yScale). on("zoomstart", zoomstart). on("zoom", redraw); function zoomstart() { node.each(function(d) { d.selected = false; d.previouslySelected = false; }); node.classed("selected", false); } function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); } var brusher = d3.svg.brush() //.x(d3.scale.identity().domain([0, width])) //.y(d3.scale.identity().domain([0, height])) .x(xScale) .y(yScale) .on("brushstart", function(d) { node.each(function(d) { d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); node.classed("selected", function(d) { return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); }); var svg_graph = svg.append('svg:g') .call(zoomer) //.call(brusher) var rect = svg_graph.append('svg:rect') .attr('width', width) .attr('height', height) .attr('fill', 'transparent') //.attr('opacity', 0.5) .attr('stroke', 'transparent') .attr('stroke-width', 1) //.attr("pointer-events", "all") .attr("id", "zrect") var brush = svg_graph.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush"); var vis = svg_graph.append("svg:g"); vis.attr('fill', 'red') .attr('stroke', 'black') .attr('stroke-width', 1) .attr('opacity', 0.5) .attr('id', 'vis') brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto'); var link = vis.append("g") .attr("class", "link") .selectAll("line"); var node = vis.append("g") .attr("class", "node") .selectAll("circle"); center_view = function() { // Center the view on the molecule(s) and scale it so that everything // fits in the window if (nodeGraph === null) return; var nodes = nodeGraph.nodes; //no molecules, nothing to do if (nodes.length === 0) return; // Get the bounding box min_x = d3.min(nodes.map(function(d) {return d.x;})); min_y = d3.min(nodes.map(function(d) {return d.y;})); max_x = d3.max(nodes.map(function(d) {return d.x;})); max_y = d3.max(nodes.map(function(d) {return d.y;})); // The width and the height of the graph mol_width = max_x - min_x; mol_height = max_y - min_y; // how much larger the drawing area is than the width and the height width_ratio = width / mol_width; height_ratio = height / mol_height; // we need to fit it in both directions, so we scale according to // the direction in which we need to shrink the most min_ratio = Math.min(width_ratio, height_ratio) * 0.8; // the new dimensions of the molecule new_mol_width = mol_width * min_ratio; new_mol_height = mol_height * min_ratio; // translate so that it's in the center of the window x_trans = -(min_x) * min_ratio + (width - new_mol_width) / 2; y_trans = -(min_y) * min_ratio + (height - new_mol_height) / 2; // do the actual moving vis.attr("transform", "translate(" + [x_trans, y_trans] + ")" + " scale(" + min_ratio + ")"); // tell the zoomer what we did so that next we zoom, it uses the // transformation we entered here zoomer.translate([x_trans, y_trans ]); zoomer.scale(min_ratio); }; function dragended(d) { //d3.select(self).classed("dragging", false); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed &= ~6; }) } d3.json("graph.json", function(error, graph) { nodeGraph = graph; graph.links.forEach(function(d) { d.source = graph.nodes[d.source]; d.target = graph.nodes[d.target]; }); link = link.data(graph.links).enter().append("line") .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; }); var force = d3.layout.force() .charge(-120) .linkDistance(30) .nodes(graph.nodes) .links(graph.links) .size([width, height]) .start(); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); if (!d.selected && !shiftKey) { // if this node isn't selected, then we have to unselect every other node node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }); } d3.select(this).classed("selected", function(p) { d.previouslySelected = d.selected; return d.selected = true; }); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed |= 2; }) } function dragged(d) { node.filter(function(d) { return d.selected; }) .each(function(d) { d.x += d3.event.dx; d.y += d3.event.dy; d.px += d3.event.dx; d.py += d3.event.dy; }) force.resume(); } node = node.data(graph.nodes).enter().append("circle") .attr("r", 4) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .on("dblclick", function(d) { d3.event.stopPropagation(); }) .on("click", function(d) { if (d3.event.defaultPrevented) return; if (!shiftKey) { //if the shift key isn't down, unselect everything node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }) } // always select this node d3.select(this).classed("selected", d.selected = !d.previouslySelected); }) .on("mouseup", function(d) { //if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false); }) .call(d3.behavior.drag() .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended)); function tick() { 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('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); }; force.on("tick", tick); }); function keydown() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; console.log('d3.event', d3.event) if (d3.event.keyCode == 67) { //the 'c' key center_view(); } if (shiftKey) { svg_graph.call(zoomer) .on("mousedown.zoom", null) .on("touchstart.zoom", null) .on("touchmove.zoom", null) .on("touchend.zoom", null); //svg_graph.on('zoom', null); vis.selectAll('g.gnode') .on('mousedown.drag', null); brush.select('.background').style('cursor', 'crosshair') brush.call(brusher); } } function keyup() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto') svg_graph.call(zoomer); } } -
Peter Kerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
LoadingSorry, something went wrong. Reload?Sorry, we cannot display this file.Sorry, this file is invalid so it cannot be displayed. -
Peter Kerpedjiev revised this gist
Feb 7, 2015 . 2 changed files with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,7 @@ } .node .selected { stroke: black; } .link { @@ -23,5 +23,5 @@ </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="plot.js"></script> LoadingSorry, something went wrong. Reload?Sorry, we cannot display this file.Sorry, this file is invalid so it cannot be displayed. -
pkerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 7 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,8 @@ This is an extension of Mike Bostock's [Draggable Network II](http://bl.ocks.org/mbostock/4566102) example, allowing one to drag multiple nodes in a force-directed graph. Nodes can be selected by holding the shift key and either dragging on the canvas or clicking on specific nodes. The selection and dragging semantics aim to mirror those of most window managers: 1. Shift clicking on a node toggles whether it is selected 2. Clicking (without shift) on a node, selects it and deselects everything else. 3. Shift dragging on the canvas toggles the selection status of the nodes enclosed within it. 4. Dragging a set of selected nodes drags all of them. 5. Clicking on the canvas de-selects everything. -
pkerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 174 additions and 180 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,237 +1,231 @@ var width = 960, height = 500, shiftKey, ctrlKey; var xScale = d3.scale.linear() .domain([0,width]).range([0,width]); var yScale = d3.scale.linear() .domain([0,height]).range([0, height]); var svg = d3.select("body") .attr("tabindex", 1) .on("keydown.brush", keydown) .on("keyup.brush", keyup) .each(function() { this.focus(); }) .append("svg") .attr("width", width) .attr("height", height); var zoomer = d3.behavior.zoom(). scaleExtent([0.1,10]). x(xScale). y(yScale). on("zoomstart", zoomstart). on("zoom", redraw); function zoomstart() { node.each(function(d) { d.selected = false; d.previouslySelected = false; }); node.classed("selected", false); } function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); } var brusher = d3.svg.brush() //.x(d3.scale.identity().domain([0, width])) //.y(d3.scale.identity().domain([0, height])) .x(xScale) .y(yScale) .on("brushstart", function(d) { node.each(function(d) { d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); node.classed("selected", function(d) { return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); }) var svg_graph = svg.append('svg:g') .call(zoomer) //.call(brusher) var rect = svg_graph.append('svg:rect') .attr('width', width) .attr('height', height) .attr('fill', 'transparent') //.attr('opacity', 0.5) .attr('stroke', 'transparent') .attr('stroke-width', 1) //.attr("pointer-events", "all") .attr("id", "zrect") var brush = svg_graph.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush"); var vis = svg_graph.append("svg:g"); vis.attr('fill', 'red') .attr('stroke', 'black') .attr('stroke-width', 1) .attr('opacity', 0.5) .attr('id', 'vis') brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto'); var link = vis.append("g") .attr("class", "link") .selectAll("line"); var node = vis.append("g") .attr("class", "node") .selectAll("circle"); function dragended(d) { //d3.select(self).classed("dragging", false); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed &= ~6; }) } d3.json("graph.json", function(error, graph) { graph.links.forEach(function(d) { d.source = graph.nodes[d.source]; d.target = graph.nodes[d.target]; }); link = link.data(graph.links).enter().append("line") .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; }); var force = d3.layout.force() .charge(-120) .linkDistance(30) .nodes(graph.nodes) .links(graph.links) .size([width, height]) .start(); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); if (!d.selected && !shiftKey) { // if this node isn't selected, then we have to unselect every other node node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }); } d3.select(this).classed("selected", function(p) { d.previouslySelected = d.selected; return d.selected = true; }); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed |= 2; }) } function dragged(d) { node.filter(function(d) { return d.selected; }) .each(function(d) { d.x += d3.event.dx; d.y += d3.event.dy; d.px += d3.event.dx; d.py += d3.event.dy; }) force.resume(); } node = node.data(graph.nodes).enter().append("circle") .attr("r", 4) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .on("dblclick", function(d) { d3.event.stopPropagation(); }) .on("click", function(d) { if (d3.event.defaultPrevented) return; if (!shiftKey) { //if the shift key isn't down, unselect everything node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }) } // always select this node d3.select(this).classed("selected", d.selected = !d.previouslySelected); }) .on("mouseup", function(d) { //if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false); }) .call(d3.behavior.drag() .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended)); function tick() { 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('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); }; force.on("tick", tick); }); function keydown() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; if (shiftKey) { svg_graph.call(zoomer) .on("mousedown.zoom", null) .on("touchstart.zoom", null) .on("touchmove.zoom", null) .on("touchend.zoom", null); //svg_graph.on('zoom', null); vis.selectAll('g.gnode') .on('mousedown.drag', null); brush.select('.background').style('cursor', 'crosshair') brush.call(brusher); } } function keyup() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto') svg_graph.call(zoomer); -
pkerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 1 addition and 243 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -24,246 +24,4 @@ </style> <body> <script src="d3.js"></script> <script src="plot.js"></script> -
pkerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 238 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,238 @@ var width = 960, height = 500, shiftKey, ctrlKey; var xScale = d3.scale.linear() .domain([0,width]).range([0,width]); var yScale = d3.scale.linear() .domain([0,height]).range([0, height]); var svg = d3.select("body") .attr("tabindex", 1) .on("keydown.brush", keydown) .on("keyup.brush", keyup) .each(function() { this.focus(); }) .append("svg") .attr("width", width) .attr("height", height); var zoomer = d3.behavior.zoom(). scaleExtent([0.1,10]). x(xScale). y(yScale). on("zoomstart", zoomstart). on("zoom", redraw); function zoomstart() { node.each(function(d) { d.selected = false; d.previouslySelected = false; }) node.classed("selected", false); } function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); } var brusher = d3.svg.brush() //.x(d3.scale.identity().domain([0, width])) //.y(d3.scale.identity().domain([0, height])) .x(xScale) .y(yScale) .on("brushstart", function(d) { console.log("brushstart"); node.each(function(d) { console.log('d.previouslySelect:', d.previouslySelected); d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); console.log('extent:', extent.toString()); console.log('brusher.x().range()', brusher.y().domain(), brusher.x().range()); node.classed("selected", function(d) { return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); }) var svg_graph = svg.append('svg:g') .call(zoomer) //.call(brusher) var rect = svg_graph.append('svg:rect') .attr('width', width) .attr('height', height) .attr('fill', 'transparent') //.attr('opacity', 0.5) .attr('stroke', 'transparent') .attr('stroke-width', 1) //.attr("pointer-events", "all") .attr("id", "zrect") var brush = svg_graph.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush"); var vis = svg_graph.append("svg:g"); vis.attr('fill', 'red') .attr('stroke', 'black') .attr('stroke-width', 1) .attr('opacity', 0.5) .attr('id', 'vis') console.log('ole'); brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); var link = vis.append("g") .attr("class", "link") .selectAll("line"); var node = vis.append("g") .attr("class", "node") .selectAll("circle"); function dragended(d) { //d3.select(self).classed("dragging", false); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed &= ~6; }) } d3.json("graph.json", function(error, graph) { graph.links.forEach(function(d) { d.source = graph.nodes[d.source]; d.target = graph.nodes[d.target]; }); link = link.data(graph.links).enter().append("line") .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; }); var force = d3.layout.force() .charge(-120) .linkDistance(30) .nodes(graph.nodes) .links(graph.links) .size([width, height]) .start(); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); console.log('dragstarted', d.previouslySelected, d.selected) d3.select(this).classed("selected", function(p) { d.previouslySelected = d.selected; return d.selected = true; }); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed |= 2; }) } function dragged(d) { console.log('dragged') node.filter(function(d) { return d.selected; }) .each(function(d) { d.x += d3.event.dx; d.y += d3.event.dy; d.px += d3.event.dx; d.py += d3.event.dy; }) force.resume(); } node = node.data(graph.nodes).enter().append("circle") .attr("r", 4) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .on("dblclick", function(d) { d3.event.stopPropagation(); }) .on("click", function(d) { console.log('click') console.log('click', d.previouslySelected, d.selected) if (d3.event.defaultPrevented) return; console.log('click1') if (!shiftKey) { //if the shift key isn't down, unselect everything node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }) } // always select this node d3.select(this).classed("selected", d.selected = !d.previouslySelected); }) .on("mouseup", function(d) { //if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false); }) .call(d3.behavior.drag() .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended)); function tick() { 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('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); }; force.on("tick", tick); }); function keydown() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; if (shiftKey) { svg_graph.call(zoomer) .on("mousedown.zoom", null) .on("touchstart.zoom", null) .on("touchmove.zoom", null) .on("touchend.zoom", null); //svg_graph.on('zoom', null); vis.selectAll('g.gnode') .on('mousedown.drag', null); brush.select('.background').style('cursor', 'crosshair') brush.call(brusher); } } function keyup() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto') svg_graph.call(zoomer); } -
pkerpedjiev renamed this gist
Feb 7, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
pkerpedjiev revised this gist
Feb 7, 2015 . 2 changed files with 1330 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,1330 @@ { "nodes":[ { "x":444, "y":275 }, { "x":378, "y":324 }, { "x":478, "y":278 }, { "x":471, "y":256 }, { "x":382, "y":269 }, { "x":371, "y":247 }, { "x":359, "y":276 }, { "x":364, "y":302 }, { "x":400, "y":330 }, { "x":388, "y":298 }, { "x":524, "y":296 }, { "x":570, "y":243 }, { "x":552, "y":159 }, { "x":502, "y":287 }, { "x":511, "y":313 }, { "x":513, "y":265 }, { "x":602, "y":132 }, { "x":610, "y":90 }, { "x":592, "y":91 }, { "x":575, "y":89 }, { "x":607, "y":73 }, { "x":591, "y":68 }, { "x":574, "y":73 }, { "x":589, "y":149 }, { "x":620, "y":205 }, { "x":621, "y":230 }, { "x":589, "y":234 }, { "x":602, "y":223 }, { "x":548, "y":188 }, { "x":532, "y":196 }, { "x":548, "y":114 }, { "x":575, "y":174 }, { "x":497, "y":250 }, { "x":576, "y":196 }, { "x":504, "y":201 }, { "x":494, "y":186 }, { "x":482, "y":199 }, { "x":505, "y":219 }, { "x":486, "y":216 }, { "x":590, "y":306 }, { "x":677, "y":169 }, { "x":657, "y":258 }, { "x":667, "y":205 }, { "x":552, "y":227 }, { "x":518, "y":173 }, { "x":473, "y":125 }, { "x":796, "y":260 }, { "x":731, "y":272 }, { "x":642, "y":288 }, { "x":576, "y":269 }, { "x":605, "y":187 }, { "x":559, "y":289 }, { "x":544, "y":356 }, { "x":505, "y":365 }, { "x":579, "y":289 }, { "x":619, "y":282 }, { "x":574, "y":329 }, { "x":664, "y":306 }, { "x":627, "y":304 }, { "x":643, "y":327 }, { "x":664, "y":348 }, { "x":665, "y":327 }, { "x":653, "y":317 }, { "x":650, "y":338 }, { "x":622, "y":321 }, { "x":633, "y":338 }, { "x":647, "y":357 }, { "x":718, "y":362 }, { "x":636, "y":240 }, { "x":640, "y":227 }, { "x":617, "y":249 }, { "x":631, "y":254 }, { "x":566, "y":213 }, { "x":713, "y":322 }, { "x":716, "y":298 }, { "x":666, "y":241 }, { "x":627, "y":355 } ], "links":[ { "source":1, "target":0 }, { "source":2, "target":0 }, { "source":3, "target":0 }, { "source":3, "target":2 }, { "source":4, "target":0 }, { "source":5, "target":0 }, { "source":6, "target":0 }, { "source":7, "target":0 }, { "source":8, "target":0 }, { "source":9, "target":0 }, { "source":11, "target":10 }, { "source":11, "target":3 }, { "source":11, "target":2 }, { "source":11, "target":0 }, { "source":12, "target":11 }, { "source":13, "target":11 }, { "source":14, "target":11 }, { "source":15, "target":11 }, { "source":17, "target":16 }, { "source":18, "target":16 }, { "source":18, "target":17 }, { "source":19, "target":16 }, { "source":19, "target":17 }, { "source":19, "target":18 }, { "source":20, "target":16 }, { "source":20, "target":17 }, { "source":20, "target":18 }, { "source":20, "target":19 }, { "source":21, "target":16 }, { "source":21, "target":17 }, { "source":21, "target":18 }, { "source":21, "target":19 }, { "source":21, "target":20 }, { "source":22, "target":16 }, { "source":22, "target":17 }, { "source":22, "target":18 }, { "source":22, "target":19 }, { "source":22, "target":20 }, { "source":22, "target":21 }, { "source":23, "target":16 }, { "source":23, "target":17 }, { "source":23, "target":18 }, { "source":23, "target":19 }, { "source":23, "target":20 }, { "source":23, "target":21 }, { "source":23, "target":22 }, { "source":23, "target":12 }, { "source":23, "target":11 }, { "source":24, "target":23 }, { "source":24, "target":11 }, { "source":25, "target":24 }, { "source":25, "target":23 }, { "source":25, "target":11 }, { "source":26, "target":24 }, { "source":26, "target":11 }, { "source":26, "target":16 }, { "source":26, "target":25 }, { "source":27, "target":11 }, { "source":27, "target":23 }, { "source":27, "target":25 }, { "source":27, "target":24 }, { "source":27, "target":26 }, { "source":28, "target":11 }, { "source":28, "target":27 }, { "source":29, "target":23 }, { "source":29, "target":27 }, { "source":29, "target":11 }, { "source":30, "target":23 }, { "source":31, "target":30 }, { "source":31, "target":11 }, { "source":31, "target":23 }, { "source":31, "target":27 }, { "source":32, "target":11 }, { "source":33, "target":11 }, { "source":33, "target":27 }, { "source":34, "target":11 }, { "source":34, "target":29 }, { "source":35, "target":11 }, { "source":35, "target":34 }, { "source":35, "target":29 }, { "source":36, "target":34 }, { "source":36, "target":35 }, { "source":36, "target":11 }, { "source":36, "target":29 }, { "source":37, "target":34 }, { "source":37, "target":35 }, { "source":37, "target":36 }, { "source":37, "target":11 }, { "source":37, "target":29 }, { "source":38, "target":34 }, { "source":38, "target":35 }, { "source":38, "target":36 }, { "source":38, "target":37 }, { "source":38, "target":11 }, { "source":38, "target":29 }, { "source":39, "target":25 }, { "source":40, "target":25 }, { "source":41, "target":24 }, { "source":41, "target":25 }, { "source":42, "target":41 }, { "source":42, "target":25 }, { "source":42, "target":24 }, { "source":43, "target":11 }, { "source":43, "target":26 }, { "source":43, "target":27 }, { "source":44, "target":28 }, { "source":44, "target":11 }, { "source":45, "target":28 }, { "source":47, "target":46 }, { "source":48, "target":47 }, { "source":48, "target":25 }, { "source":48, "target":27 }, { "source":48, "target":11 }, { "source":49, "target":26 }, { "source":49, "target":11 }, { "source":50, "target":49 }, { "source":50, "target":24 }, { "source":51, "target":49 }, { "source":51, "target":26 }, { "source":51, "target":11 }, { "source":52, "target":51 }, { "source":52, "target":39 }, { "source":53, "target":51 }, { "source":54, "target":51 }, { "source":54, "target":49 }, { "source":54, "target":26 }, { "source":55, "target":51 }, { "source":55, "target":49 }, { "source":55, "target":39 }, { "source":55, "target":54 }, { "source":55, "target":26 }, { "source":55, "target":11 }, { "source":55, "target":16 }, { "source":55, "target":25 }, { "source":55, "target":41 }, { "source":55, "target":48 }, { "source":56, "target":49 }, { "source":56, "target":55 }, { "source":57, "target":55 }, { "source":57, "target":41 }, { "source":57, "target":48 }, { "source":58, "target":55 }, { "source":58, "target":48 }, { "source":58, "target":27 }, { "source":58, "target":57 }, { "source":58, "target":11 }, { "source":59, "target":58 }, { "source":59, "target":55 }, { "source":59, "target":48 }, { "source":59, "target":57 }, { "source":60, "target":48 }, { "source":60, "target":58 }, { "source":60, "target":59 }, { "source":61, "target":48 }, { "source":61, "target":58 }, { "source":61, "target":60 }, { "source":61, "target":59 }, { "source":61, "target":57 }, { "source":61, "target":55 }, { "source":62, "target":55 }, { "source":62, "target":58 }, { "source":62, "target":59 }, { "source":62, "target":48 }, { "source":62, "target":57 }, { "source":62, "target":41 }, { "source":62, "target":61 }, { "source":62, "target":60 }, { "source":63, "target":59 }, { "source":63, "target":48 }, { "source":63, "target":62 }, { "source":63, "target":57 }, { "source":63, "target":58 }, { "source":63, "target":61 }, { "source":63, "target":60 }, { "source":63, "target":55 }, { "source":64, "target":55 }, { "source":64, "target":62 }, { "source":64, "target":48 }, { "source":64, "target":63 }, { "source":64, "target":58 }, { "source":64, "target":61 }, { "source":64, "target":60 }, { "source":64, "target":59 }, { "source":64, "target":57 }, { "source":64, "target":11 }, { "source":65, "target":63 }, { "source":65, "target":64 }, { "source":65, "target":48 }, { "source":65, "target":62 }, { "source":65, "target":58 }, { "source":65, "target":61 }, { "source":65, "target":60 }, { "source":65, "target":59 }, { "source":65, "target":57 }, { "source":65, "target":55 }, { "source":66, "target":64 }, { "source":66, "target":58 }, { "source":66, "target":59 }, { "source":66, "target":62 }, { "source":66, "target":65 }, { "source":66, "target":48 }, { "source":66, "target":63 }, { "source":66, "target":61 }, { "source":66, "target":60 }, { "source":67, "target":57 }, { "source":68, "target":25 }, { "source":68, "target":11 }, { "source":68, "target":24 }, { "source":68, "target":27 }, { "source":68, "target":48 }, { "source":68, "target":41 }, { "source":69, "target":25 }, { "source":69, "target":68 }, { "source":69, "target":11 }, { "source":69, "target":24 }, { "source":69, "target":27 }, { "source":69, "target":48 }, { "source":69, "target":41 }, { "source":70, "target":25 }, { "source":70, "target":69 }, { "source":70, "target":68 }, { "source":70, "target":11 }, { "source":70, "target":24 }, { "source":70, "target":27 }, { "source":70, "target":41 }, { "source":70, "target":58 }, { "source":71, "target":27 }, { "source":71, "target":69 }, { "source":71, "target":68 }, { "source":71, "target":70 }, { "source":71, "target":11 }, { "source":71, "target":48 }, { "source":71, "target":41 }, { "source":71, "target":25 }, { "source":72, "target":26 }, { "source":72, "target":27 }, { "source":72, "target":11 }, { "source":73, "target":48 }, { "source":74, "target":48 }, { "source":74, "target":73 }, { "source":75, "target":69 }, { "source":75, "target":68 }, { "source":75, "target":25 }, { "source":75, "target":48 }, { "source":75, "target":41 }, { "source":75, "target":70 }, { "source":75, "target":71 }, { "source":76, "target":64 }, { "source":76, "target":65 }, { "source":76, "target":66 }, { "source":76, "target":63 }, { "source":76, "target":62 }, { "source":76, "target":48 }, { "source":76, "target":58 } ] } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,3 @@ <!DOCTYPE html> <meta charset="utf-8"> <style> -
pkerpedjiev revised this gist
Feb 7, 2015 . 1 changed file with 207 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,40 @@ <!DOCTYPE html> <meta charset="utf-8"> <style> .node { stroke: #fff; stroke-width: 1.5px; } .node .selected { stroke: red; } .link { stroke: #999; } .brush .extent { fill-opacity: .1; stroke: #fff; shape-rendering: crispEdges; } </style> <body> <script src="d3.js"></script> <script> var width = 960, height = 500, shiftKey, ctrlKey; var xScale = d3.scale.linear() .domain([0,width]).range([0,width]); var yScale = d3.scale.linear() .domain([0,height]).range([0, height]); var svg = d3.select("body") .attr("tabindex", 1) @@ -11,19 +45,104 @@ .attr("width", width) .attr("height", height); var zoomer = d3.behavior.zoom(). scaleExtent([0.1,10]). x(xScale). y(yScale). on("zoomstart", zoomstart). on("zoom", redraw); function zoomstart() { node.each(function(d) { d.selected = false; d.previouslySelected = false; }) node.classed("selected", false); } function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); } var brusher = d3.svg.brush() //.x(d3.scale.identity().domain([0, width])) //.y(d3.scale.identity().domain([0, height])) .x(xScale) .y(yScale) .on("brushstart", function(d) { console.log("brushstart"); node.each(function(d) { console.log('d.previouslySelect:', d.previouslySelected); d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); console.log('extent:', extent.toString()); console.log('brusher.x().range()', brusher.y().domain(), brusher.x().range()); node.classed("selected", function(d) { return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); }) var svg_graph = svg.append('svg:g') .call(zoomer) //.call(brusher) var rect = svg_graph.append('svg:rect') .attr('width', width) .attr('height', height) .attr('fill', 'transparent') //.attr('opacity', 0.5) .attr('stroke', 'transparent') .attr('stroke-width', 1) //.attr("pointer-events", "all") .attr("id", "zrect") var brush = svg_graph.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush"); var vis = svg_graph.append("svg:g"); vis.attr('fill', 'red') .attr('stroke', 'black') .attr('stroke-width', 1) .attr('opacity', 0.5) .attr('id', 'vis') console.log('ole'); brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); var link = vis.append("g") .attr("class", "link") .selectAll("line"); var node = vis.append("g") .attr("class", "node") .selectAll("circle"); function dragended(d) { //d3.select(self).classed("dragging", false); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed &= ~6; }) } d3.json("graph.json", function(error, graph) { graph.links.forEach(function(d) { d.source = graph.nodes[d.source]; @@ -36,24 +155,6 @@ .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); var force = d3.layout.force() .charge(-120) @@ -63,58 +164,107 @@ .size([width, height]) .start(); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); console.log('dragstarted', d.previouslySelected, d.selected) d3.select(this).classed("selected", function(p) { d.previouslySelected = d.selected; return d.selected = true; }); node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed |= 2; }) } function dragged(d) { console.log('dragged') node.filter(function(d) { return d.selected; }) .each(function(d) { d.x += d3.event.dx; d.y += d3.event.dy; d.px += d3.event.dx; d.py += d3.event.dy; }) force.resume(); } node = node.data(graph.nodes).enter().append("circle") .attr("r", 4) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .on("dblclick", function(d) { d3.event.stopPropagation(); }) .on("click", function(d) { console.log('click') console.log('click', d.previouslySelected, d.selected) if (d3.event.defaultPrevented) return; console.log('click1') if (!shiftKey) { //if the shift key isn't down, unselect everything node.classed("selected", function(p) { return p.selected = p.previouslySelected = false; }) } // always select this node d3.select(this).classed("selected", d.selected = !d.previouslySelected); }) .on("mouseup", function(d) { //if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false); }) .call(d3.behavior.drag() .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended)); function tick() { 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('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); }; force.on("tick", tick); }); function keydown() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; if (shiftKey) { svg_graph.call(zoomer) .on("mousedown.zoom", null) .on("touchstart.zoom", null) .on("touchmove.zoom", null) .on("touchend.zoom", null); //svg_graph.on('zoom', null); vis.selectAll('g.gnode') .on('mousedown.drag', null); brush.select('.background').style('cursor', 'crosshair') brush.call(brusher); } } function keyup() { shiftKey = d3.event.shiftKey || d3.event.metaKey; ctrlKey = d3.event.ctrlKey; brush.call(brusher) .on("mousedown.brush", null) .on("touchstart.brush", null) .on("touchmove.brush", null) .on("touchend.brush", null); brush.select('.background').style('cursor', 'auto') svg_graph.call(zoomer); } </script> -
pkerpedjiev revised this gist
Jan 26, 2015 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1,3 @@ This is an extension of Mike Bostock's [Draggable Network II](http://bl.ocks.org/mbostock/4566102) example, allowing one to drag multiple nodes in a force-directed graph. Nodes can be selected by dragging on the canvas and moved by dragging on the selected nodes. The key changes are the additional handlers for `dragstart` and `dragend` which mark the selected nodes as `fixed` when starting to drag and unmark them when the dragging is complete so that the force can be computed. -
pkerpedjiev revised this gist
Jan 26, 2015 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ This is an extension of Mike Bostock's [Draggable Network II](http://bl.ocks.org/mbostock/4566102) example, allowing one to drag multiple nodes in a force-directed graph. The key changes are the additional handlers for `dragstart` and `dragend` which mark the selected nodes as `fixed` when starting to drag and unmark them when the dragging is complete so that the force can be computed. -
pkerpedjiev renamed this gist
Jan 26, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
pkerpedjiev revised this gist
Jan 26, 2015 . No changes.There are no files selected for viewing
-
pkerpedjiev created this gist
Jan 26, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,120 @@ var width = 400, height = 500, shiftKey; var svg = d3.select("body") .attr("tabindex", 1) .on("keydown.brush", keydown) .on("keyup.brush", keyup) .each(function() { this.focus(); }) .append("svg") .attr("width", width) .attr("height", height); var link = svg.append("g") .attr("class", "link") .selectAll("line"); var brush = svg.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush"); var node = svg.append("g") .attr("class", "node") .selectAll("circle"); var graph = {"nodes":[{"x":444,"y":275},{"x":378,"y":324},{"x":478,"y":278},{"x":471,"y":256},{"x":382,"y":269},{"x":371,"y":247},{"x":359,"y":276},{"x":364,"y":302},{"x":400,"y":330},{"x":388,"y":298},{"x":524,"y":296},{"x":570,"y":243},{"x":552,"y":159},{"x":502,"y":287},{"x":511,"y":313},{"x":513,"y":265},{"x":602,"y":132},{"x":610,"y":90},{"x":592,"y":91},{"x":575,"y":89},{"x":607,"y":73},{"x":591,"y":68},{"x":574,"y":73},{"x":589,"y":149},{"x":620,"y":205},{"x":621,"y":230},{"x":589,"y":234},{"x":602,"y":223},{"x":548,"y":188},{"x":532,"y":196},{"x":548,"y":114},{"x":575,"y":174},{"x":497,"y":250},{"x":576,"y":196},{"x":504,"y":201},{"x":494,"y":186},{"x":482,"y":199},{"x":505,"y":219},{"x":486,"y":216},{"x":590,"y":306},{"x":677,"y":169},{"x":657,"y":258},{"x":667,"y":205},{"x":552,"y":227},{"x":518,"y":173},{"x":473,"y":125},{"x":796,"y":260},{"x":731,"y":272},{"x":642,"y":288},{"x":576,"y":269},{"x":605,"y":187},{"x":559,"y":289},{"x":544,"y":356},{"x":505,"y":365},{"x":579,"y":289},{"x":619,"y":282},{"x":574,"y":329},{"x":664,"y":306},{"x":627,"y":304},{"x":643,"y":327},{"x":664,"y":348},{"x":665,"y":327},{"x":653,"y":317},{"x":650,"y":338},{"x":622,"y":321},{"x":633,"y":338},{"x":647,"y":357},{"x":718,"y":362},{"x":636,"y":240},{"x":640,"y":227},{"x":617,"y":249},{"x":631,"y":254},{"x":566,"y":213},{"x":713,"y":322},{"x":716,"y":298},{"x":666,"y":241},{"x":627,"y":355}],"links":[{"source":1,"target":0},{"source":2,"target":0},{"source":3,"target":0},{"source":3,"target":2},{"source":4,"target":0},{"source":5,"target":0},{"source":6,"target":0},{"source":7,"target":0},{"source":8,"target":0},{"source":9,"target":0},{"source":11,"target":10},{"source":11,"target":3},{"source":11,"target":2},{"source":11,"target":0},{"source":12,"target":11},{"source":13,"target":11},{"source":14,"target":11},{"source":15,"target":11},{"source":17,"target":16},{"source":18,"target":16},{"source":18,"target":17},{"source":19,"target":16},{"source":19,"target":17},{"source":19,"target":18},{"source":20,"target":16},{"source":20,"target":17},{"source":20,"target":18},{"source":20,"target":19},{"source":21,"target":16},{"source":21,"target":17},{"source":21,"target":18},{"source":21,"target":19},{"source":21,"target":20},{"source":22,"target":16},{"source":22,"target":17},{"source":22,"target":18},{"source":22,"target":19},{"source":22,"target":20},{"source":22,"target":21},{"source":23,"target":16},{"source":23,"target":17},{"source":23,"target":18},{"source":23,"target":19},{"source":23,"target":20},{"source":23,"target":21},{"source":23,"target":22},{"source":23,"target":12},{"source":23,"target":11},{"source":24,"target":23},{"source":24,"target":11},{"source":25,"target":24},{"source":25,"target":23},{"source":25,"target":11},{"source":26,"target":24},{"source":26,"target":11},{"source":26,"target":16},{"source":26,"target":25},{"source":27,"target":11},{"source":27,"target":23},{"source":27,"target":25},{"source":27,"target":24},{"source":27,"target":26},{"source":28,"target":11},{"source":28,"target":27},{"source":29,"target":23},{"source":29,"target":27},{"source":29,"target":11},{"source":30,"target":23},{"source":31,"target":30},{"source":31,"target":11},{"source":31,"target":23},{"source":31,"target":27},{"source":32,"target":11},{"source":33,"target":11},{"source":33,"target":27},{"source":34,"target":11},{"source":34,"target":29},{"source":35,"target":11},{"source":35,"target":34},{"source":35,"target":29},{"source":36,"target":34},{"source":36,"target":35},{"source":36,"target":11},{"source":36,"target":29},{"source":37,"target":34},{"source":37,"target":35},{"source":37,"target":36},{"source":37,"target":11},{"source":37,"target":29},{"source":38,"target":34},{"source":38,"target":35},{"source":38,"target":36},{"source":38,"target":37},{"source":38,"target":11},{"source":38,"target":29},{"source":39,"target":25},{"source":40,"target":25},{"source":41,"target":24},{"source":41,"target":25},{"source":42,"target":41},{"source":42,"target":25},{"source":42,"target":24},{"source":43,"target":11},{"source":43,"target":26},{"source":43,"target":27},{"source":44,"target":28},{"source":44,"target":11},{"source":45,"target":28},{"source":47,"target":46},{"source":48,"target":47},{"source":48,"target":25},{"source":48,"target":27},{"source":48,"target":11},{"source":49,"target":26},{"source":49,"target":11},{"source":50,"target":49},{"source":50,"target":24},{"source":51,"target":49},{"source":51,"target":26},{"source":51,"target":11},{"source":52,"target":51},{"source":52,"target":39},{"source":53,"target":51},{"source":54,"target":51},{"source":54,"target":49},{"source":54,"target":26},{"source":55,"target":51},{"source":55,"target":49},{"source":55,"target":39},{"source":55,"target":54},{"source":55,"target":26},{"source":55,"target":11},{"source":55,"target":16},{"source":55,"target":25},{"source":55,"target":41},{"source":55,"target":48},{"source":56,"target":49},{"source":56,"target":55},{"source":57,"target":55},{"source":57,"target":41},{"source":57,"target":48},{"source":58,"target":55},{"source":58,"target":48},{"source":58,"target":27},{"source":58,"target":57},{"source":58,"target":11},{"source":59,"target":58},{"source":59,"target":55},{"source":59,"target":48},{"source":59,"target":57},{"source":60,"target":48},{"source":60,"target":58},{"source":60,"target":59},{"source":61,"target":48},{"source":61,"target":58},{"source":61,"target":60},{"source":61,"target":59},{"source":61,"target":57},{"source":61,"target":55},{"source":62,"target":55},{"source":62,"target":58},{"source":62,"target":59},{"source":62,"target":48},{"source":62,"target":57},{"source":62,"target":41},{"source":62,"target":61},{"source":62,"target":60},{"source":63,"target":59},{"source":63,"target":48},{"source":63,"target":62},{"source":63,"target":57},{"source":63,"target":58},{"source":63,"target":61},{"source":63,"target":60},{"source":63,"target":55},{"source":64,"target":55},{"source":64,"target":62},{"source":64,"target":48},{"source":64,"target":63},{"source":64,"target":58},{"source":64,"target":61},{"source":64,"target":60},{"source":64,"target":59},{"source":64,"target":57},{"source":64,"target":11},{"source":65,"target":63},{"source":65,"target":64},{"source":65,"target":48},{"source":65,"target":62},{"source":65,"target":58},{"source":65,"target":61},{"source":65,"target":60},{"source":65,"target":59},{"source":65,"target":57},{"source":65,"target":55},{"source":66,"target":64},{"source":66,"target":58},{"source":66,"target":59},{"source":66,"target":62},{"source":66,"target":65},{"source":66,"target":48},{"source":66,"target":63},{"source":66,"target":61},{"source":66,"target":60},{"source":67,"target":57},{"source":68,"target":25},{"source":68,"target":11},{"source":68,"target":24},{"source":68,"target":27},{"source":68,"target":48},{"source":68,"target":41},{"source":69,"target":25},{"source":69,"target":68},{"source":69,"target":11},{"source":69,"target":24},{"source":69,"target":27},{"source":69,"target":48},{"source":69,"target":41},{"source":70,"target":25},{"source":70,"target":69},{"source":70,"target":68},{"source":70,"target":11},{"source":70,"target":24},{"source":70,"target":27},{"source":70,"target":41},{"source":70,"target":58},{"source":71,"target":27},{"source":71,"target":69},{"source":71,"target":68},{"source":71,"target":70},{"source":71,"target":11},{"source":71,"target":48},{"source":71,"target":41},{"source":71,"target":25},{"source":72,"target":26},{"source":72,"target":27},{"source":72,"target":11},{"source":73,"target":48},{"source":74,"target":48},{"source":74,"target":73},{"source":75,"target":69},{"source":75,"target":68},{"source":75,"target":25},{"source":75,"target":48},{"source":75,"target":41},{"source":75,"target":70},{"source":75,"target":71},{"source":76,"target":64},{"source":76,"target":65},{"source":76,"target":66},{"source":76,"target":63},{"source":76,"target":62},{"source":76,"target":48},{"source":76,"target":58}]} graph.links.forEach(function(d) { d.source = graph.nodes[d.source]; d.target = graph.nodes[d.target]; }); link = link.data(graph.links).enter().append("line") .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; }); brush.call(d3.svg.brush() .x(d3.scale.identity().domain([0, width])) .y(d3.scale.identity().domain([0, height])) .on("brushstart", function(d) { node.each(function(d) { d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); node.classed("selected", function(d) { return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); })); var force = d3.layout.force() .charge(-120) .linkDistance(30) .nodes(graph.nodes) .links(graph.links) .size([width, height]) .start(); node = node.data(graph.nodes).enter().append("circle") .attr("r", 4) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .on("mousedown", function(d) { if (!d.selected) { // Don't deselect on shift-drag. if (!shiftKey) node.classed("selected", function(p) { return p.selected = d === p; }); else d3.select(this).classed("selected", d.selected = true); } }) .on("mouseup", function(d) { if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false); }) .call(d3.behavior.drag() .on("dragstart", function(d1) { node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed |= 2; }) }) .on("drag", function(d1) { node.filter(function(d) { return d.selected; }) .each(function(d) { d.x += d3.event.dx; d.y += d3.event.dy; d.px += d3.event.dx; d.py += d3.event.dy; }) force.resume(); }) .on("dragend", function(d) { node.filter(function(d) { return d.selected; }) .each(function(d) { d.fixed &= ~6; }) })); function tick() { 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('cx', function(d) { return d.x; }).attr('cy', function(d) { return d.y; }); }; force.on("tick", tick); function keydown() { shiftKey = d3.event.shiftKey || d3.event.metaKey; } function keyup() { shiftKey = d3.event.shiftKey || d3.event.metaKey; }