// width y height var w = 1350; var h = 600; // declarar la fuerza y la union de los nodos por id, ahora sin charge ni centro porque no se van a correr var fuerza = d3.forceSimulation() .force("link", d3.forceLink().id(function(d){ return d.id; })) ; // insertar los datos y ponerlos en consola d3.json("actores_v5.json", function(error, data){ if (error) throw error; //verificar los datos console.log("Número de Nodos: " + data.nodes.length) console.log(data.nodes) console.log("Número de Links: " + data.edges.length) console.log(data.edges) //svg en donde dibujar var svg = d3.selectAll("body") .append("svg") .attr('width', w) .attr('height', h) ; //circulo invisible para dibujar los nodos // it's actually two arcs so we can use the getPointAtLength() and getTotalLength() methods var dim = w/2; var circle = svg.append("circle") //.attr("d", "M 40, "+(dim/2+40)+" a "+dim/2+","+dim/2+" 0 1,0 "+dim+",0 a "+dim/2+","+dim/2+" 0 1,0 "+dim*-1+",0") .attr('cx', w/2) .attr('cy', h/2) .attr('r', 250) .style("fill", "#ffffff") ; //crea las lineas con un svg y los datos de "edges" var lineas = svg.append('g') .selectAll("line") .data(data.edges) .enter() .append("path") .attr("class", function(d) { return "link " + d.tipo; }) ; //crea los nodos de acuerdo a los nombres var nodos = svg.append("g") .selectAll("circle") .data(data.nodes) .enter() .append("circle") .attr('class', function(d){ if (d.categoria == "gobierno"){ return "nodos " + d.categoria; } if (d.categoria == "patrimonio"){ return "nodos " + d.categoria; } if (d.categoria == "planeacion"){ return "nodos " + d.categoria; } if (d.categoria == "ong"){ return "nodos " + d.categoria; } if (d.categoria == "gremios"){ return "nodos " + d.categoria; } if (d.categoria == "academia"){ return "nodos " + d.categoria; } if (d.categoria == "comunidad"){ return "nodos " + d.categoria; } if (d.categoria == "privado"){ return "nodos " + d.categoria; } if (d.categoria == "medios"){ return "nodos " + d.categoria; } if (d.categoria == "otros"){ return "nodos " + d.categoria; } }) .on("mouseover", mouseEncima) .on("mouseout", mouseAfuera) .attr('r', 5) ; nodos .filter(function(d){ return d.categoria == "gobierno" || d.categoria == "patrimonio" || d.categoria == "planeacion" || d.categoria == "ong" || d.categoria == "gremios" || d.categoria == "academia" || d.categoria == "comunidad" || d.categoria == "privado" || d.categoria == "medios" || d.categoria == "otros" ; }) .style("opacity", 1) ; //titulos de los nodos nodos.append("title") .text(function(d){ return d.id; }) ; var text = svg.append("g").selectAll("text") .data(data.nodes) .attr('class', "text") .enter().append("text") .attr("x", 8) .attr("y", ".31em") .text(function(d) { return d.id; }) ; //define los nodos y los links de la simulacion fuerza.nodes(data.nodes); fuerza.force("link").links(data.edges); // calcula los espacios de los circulos en el circulo var circleCoord = function(node, index, num_nodes){ var circumference = circle.node().getTotalLength(); var pointAtLength = function(l){ return circle.node().getPointAtLength(l)}; var sectionLength = (circumference)/num_nodes; var position = sectionLength*index+sectionLength/2; return pointAtLength(circumference-position) } // define la posicion de los nodos segun el calculo anterior data.nodes.forEach(function(d, i) { var coord = circleCoord(d, i, data.nodes.length) d.fx = coord.x d.fy = coord.y }); for (i = 0; i < data.nodes.length; i++) { var angle = (i / (data.nodes.length / 2)) * Math.PI; //data.nodes.push({ 'angle': angle }); } //simulación y actualizacion de la posicion de los nodos en cada "tick" fuerza.on("tick", function(){ lineas.attr("d", function(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; }); nodos.attr("cx", function(d){ return d.x = d.fx; }) .attr('cy', function(d){ return dy = d.fy; }) ; text.attr("x", function(d){ return dx = d.fx; }) .attr('y', function(d){ return dy = d.fy; }) .style("text-anchor", "start") }); //saber si las conexiones se ven o no var toggle = 0; //Create an array logging what is connected to what var linkedByIndex = {}; for (i = 0; i < data.nodes.length; i++) { linkedByIndex[i + "," + i] = 1; }; data.edges.forEach(function (d) { linkedByIndex[d.source.index + "," + d.target.index] = 1; }); //This function looks up whether a pair are neighbours function neighboring(a, b) { return linkedByIndex[a.index + "," + b.index]; } function mouseEncima() { if (toggle == 0) { //Reduce the opacity of all but the neighbouring nodes d = d3.select(this).node().__data__; nodos .transition() .style("opacity", function (o) { return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1; }) .attr('r', function(o){ return neighboring(d, o) | neighboring(o, d) ? 10 : 5; }) ; lineas .transition() .style("stroke-opacity", function (o) { return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1; }) ; // text // .transition() // .style("opacity", function (o) { // return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1; // }) // ; //Reduce the opacity toggle = 1; } } function mouseAfuera() { nodos .filter(function(d){ return d.categoria == "gobierno" || d.categoria == "patrimonio" || d.categoria == "planeacion" || d.categoria == "ong" || d.categoria == "gremios" || d.categoria == "academia" || d.categoria == "comunidad" || d.categoria == "privado" || d.categoria == "medios" || d.categoria == "otros" ; }) .transition() .style("opacity", 1) .attr('r', 5) ; // y las lineas a 0 lineas .transition() .style("stroke-opacity", 0.1) ; // text // .transition() // .style("opacity", 0.1) // ; toggle = 0; } });