//radinal force //seperate force const margin={top:20,right:20,bottom:20,left:20}, width=$(".plot").width()-margin.left-margin.right, height=$(".plot").height()-margin.top-margin.bottom; //plot and svg const svg = d3.select('.plot') .append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append('g') .attr('transform', 'translate(' + 0 + ',' + height/2 + ')'); const rangeCategory=[], bandWidth=width/24, xBandWidth=width/6 for (let i=1;i<25;i++){ rangeCategory.push(24*i); } const scaleCategory=d3.scaleOrdinal().range(rangeCategory); const winCoordinate=d3.scaleOrdinal().range([200,400]).domain(["TURE","FALSE"]); const x = d3.scaleOrdinal().range([xBandWidth*2,xBandWidth*3,xBandWidth*4]).domain(["category","movie","detail"]) const color = d3.scaleOrdinal().range(["#ff52c8","#55E9B0","#9018F2"]).domain(["movie","category","detail"]); const tickLabels=["Awards Category","Nominated Movies","Nominated Individuals"] //load in data/ d3.queue() .defer(d3.csv,"oscars.csv",parseData) .await(ready); function ready (error,oscars) { //********************************process the data************************************/ //split function remove(d){ const newString=d.replace(/ and /g,", ").split(", ") return newString } uniqueArray = a => [...new Set(a.map(o => JSON.stringify(o)))].map(s => JSON.parse(s)) //update d.details oscars.forEach((d,i)=>{ d.details=remove(d.details)}) //flaten the details for each object const flatOscars=[]; for (let i=0;i{ dot.push({id:d.category,type:"category"},{id:d.movie,type:"movie"},{id:d.detail,type:"detail"}); line.push({source:d.category,target:d.movie},{source:d.movie,target:d.detail}) }) //****************************************reconstruct movie*****************************************// let movie=[]; oscars.forEach( (d,i)=>{ movie.push({movie:d.movie,win:d.win}) } ) movie=d3.nest().key((d)=>{return d.movie}).entries(movie); let newMovie=[] movie.forEach( (d,i)=>{ d.values.sort(function(a, b) { var nameA = a.win.toUpperCase(); var nameB = b.win.toUpperCase(); if (nameA > nameB) { return -1; } if (nameA < nameB) { return 1; } return 0; }); newMovie.push({movie:d.key,win:d.values[0].win}) } ) newMovie=uniqueArray(newMovie); console.log(newMovie) //****************************************reconstruct detail*****************************************// let detail=[]; flatOscars.forEach( (d,i)=>{ detail.push({detail:d.detail,win:d.win}) } ) detail=d3.nest().key((d)=>{return d.detail}).entries(detail); let newDetail=[] detail.forEach( (d,i)=>{ d.values.sort(function(a, b) { var nameA = a.win.toUpperCase(); var nameB = b.win.toUpperCase(); if (nameA > nameB) { return -1; } if (nameA < nameB) { return 1; } return 0; }); newDetail.push({detail:d.key,win:d.values[0].win}) } ) newDetail=uniqueArray(newDetail); console.log(newDetail) //***********************************************************************************************************// const findByMovie={}; for (let i=0;i{return tickLabels[i]})); //********************************draw graphs************************************/ const link = svg.append("g") .attr("class", "links") .selectAll("line") .data(graph.links) .enter().append("line") .attr("stroke-width", "1"); const node = svg.append("g") .attr("class", "nodes") .selectAll("circle") .data(graph.nodes) .enter().append("circle") .attr("r",(d)=>{return 4}) .attr("fill", (d) =>{ return color(d.type); }) .style("stroke",(d)=>{ if(d.win=="TRUE"){return "white"} else{return } }) .on("mouseover", fadeIn(.3)) .on("mouseout", fadeOut(1)) .on("click",(d,i)=>{return console.log(d)}) const label = svg.append("g") .attr("class", "label") .selectAll("text") .data(graph.nodes) .enter() .append("text") .text((d)=>{return d.id}) .attr("fill","white").attr("dy","2.5px").attr("dx","10px") .attr("id","text") .style("visibility", "hidden") .on("mouseover", fadeIn(.3)) .on("mouseout", fadeOut(1)) .on("click",(d,i)=>{return console.log(d)}) const simulation = d3.forceSimulation(nodes) .force("collide",d3.forceCollide().radius(6)) .force("charge",d3.forceManyBody().strength(0)) .force('x', d3.forceX().x(function(d) { return x(d.type); })) .force("y",d3.forceY().y()) .force("links",d3.forceLink().id(function(d){return d.id}).links(graph.links).strength(0)) .on("tick",ticked) //********************************hover over function************************************/ var linkedByIndex = {}; graph.links.forEach(function(d) { linkedByIndex[d.source.index + "," + d.target.index] = 1; }); function isConnected(a, b) { return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index; }; function fadeIn(opacity) { return function(d) { node.style("stroke-opacity", function(o) { thisOpacity = isConnected(d, o) ? .9 : opacity; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); label.style("visibility", function(o) { thisOpacity = isConnected(d, o) ? "visible" : "hidden"; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); link.style("stroke-opacity", opacity) .style("stroke-opacity", function(o) { return o.source === d || o.target === d ? 1 : 0; }); }; }; function fadeOut(opacity) { return function(d) { node.style("stroke-opacity", function(o) { thisOpacity = isConnected(d, o) ? 1 : opacity; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); link.style("stroke-opacity", 0.2) label.style("visibility", "hidden") }; }; //******************************************************************************************// function ticked() { 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; }); label .attr("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; }); } } function parseData(d){ return{ category:d.Category, movie:d.Movie, details:d.Details, win:d.Win } }