D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
chabb
Full window
Github gist
SOME STUFF
<html> <head> <title>STUFF</title> <meta charset="utf-8" /> <script src="https://d3js.org/d3.v3.min.js" type="text/JavaScript"></script> </head> <style> .dominos { stroke:black; } .axis text { font: 10px sans-serif; } .axis line, .axis path { fill: none; stroke: #000; stroke-width: -2px; shape-rendering: crispEdges; } div.tooltip { position: absolute; text-align: center; width: 60px; height: 28px; padding: px; font: 12px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px 8px 8px 0px; pointer-events: none; } div.tooltip > span { vertical-align: middle; line-height: 28px; } </style> <body> <div id="content"> <button id="f_empty">Filter Empty Sets</button> <button id="f_full">Display Empty Sets</button> <button id="f_sortFull">Sort (Full)</button> <button id="f_sortEmpty">Sort (Empty)</button> </div> </body> </html> <script> var D; d3.setsIntersections = function(maps) { //https://stackoverflow.com/questions/26028124/the-intersection-of-all-combinations-of-n-sets var list = []; var dominoMapping = {}; var _i = 1; var intersections = {}; var elements = 0; var numberOfSets = maps.keys().length; maps.forEach(function(k,v){ console.log(k,v.content.length); dominoMapping[k] = _i++; for(var i=0;i<v.content.length;i++) list.push({set:k,element:v.content[i]}); }) console.log(list); var limit = Math.pow(2,_i-1) for (var t=0;t<limit;t++) { intersections[t+''] = { elements:[], dominoRepresentation : computeDominoRepresentation(t) }; } var listA = d3.nest() .key(function(d) { return d.element }) .map(list); console.log(listA); elements = list.length; var keys = d3.keys(listA); for (var i=0;i<keys.length;i++) { var arrayOfSets = (listA[keys[i]]); var setId = computeIntersectionID(arrayOfSets); if (arrayOfSets.length == 1 ) { intersections[setId+''].elements.push(keys[i]); } else { intersections[setId+''].elements.push(keys[i]); } } console.log(intersections); return { intersections : intersections, distinctElements : elements, numberOfSets : numberOfSets, dominoMapping : dominoMapping, numberOfDominos : limit } function computeIntersectionID(array) { var total = 0; for (var i=0;i<array.length;i++) { var mapping = dominoMapping[array[i].set]; total = total + Math.pow(2,mapping-1); } return total; } function computeDominoRepresentation(setsId) { var domino = []; //console.log('Trying to compute',setsId,numberOfSets); for (var l=0;l<numberOfSets;l++) { id = (1 << l); var value = id & setsId; var newValue = (value >> l); console.log('testing',l+1,id,value,newValue); domino.push(newValue); } return domino; } } var contents = d3.map([ { name : "mice", content:["a","b","c","d","q","ii"]}, { name : "mdfice", content:["a","b","c","d","q","ii"]}, { name : "ghouls", content:["rip","ba","pa","qd","ii","df","fds","dfs","dfs"]}, { name : "cat", content:["gd","zd","sc","sq","ii"]}, { name : "martian", content:["qc","qp","sc","eede","bz","grm","ii"]} ],function(d) {return d.name;}); var result = d3.setsIntersections(contents); var keys = d3.keys(result.intersections); var width = 960 // should add the y axis padding height = 900 ; var dominoHeight = 400; var margin = { left : 10, right : 10, top : 10, bottom :10 } //tooltip settings // Define the div for the tooltip var div = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); // should fine the biggest sets to determine the highest range var x = d3.scale.ordinal() .rangeRoundBands([0, width], 0,0); x.domain(d3.keys(result.intersections)); var yDomino = d3.scale.ordinal() .rangeRoundBands([0, x.rangeBand()*contents.keys().length], .0,0); yDomino.domain(d3.extent([d3.keys(result.interesections)])); x.domain(d3.keys(result.intersections)); // mimick the ordinal scal with a linear scale (); var xMimickOrdinal = d3.scale.linear() .range([0,width]) var stuff = d3.extent( d3.keys(result.intersections).map(function(d) { return parseInt(d)}) ); console.log(stuff); xMimickOrdinal.domain ( [stuff[0],stuff[1]] ) var dw = x.rangeBand(); // recreate data var data = []; var filteredDatas = []; // compute immediately non filtered; var biggestNumberOfElementsInSet = 0; for (var i=0;i<keys.length;i++) { var elements = result.intersections[keys[i]].elements.length var dataPoint = {value:elements , id:keys[i],m:result.intersections[keys[i]].dominoRepresentation,w:dw,n:result.numberOfSets } data.push(dataPoint) if (dataPoint.value > 0) filteredDatas.push(dataPoint); if (elements > biggestNumberOfElementsInSet) biggestNumberOfElementsInSet = elements ; console.log('working',biggestNumberOfElementsInSet,elements); } var y = d3.scale.linear() .range([height-dominoHeight,0]) .domain(d3.extent([0,biggestNumberOfElementsInSet])); var xAxis = d3.svg.axis() .scale(x) .tickValues([]) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(biggestNumberOfElementsInSet, "-"); var yAxisDomino = d3.svg.axis() .scale(yDomino) .orient("left") .ticks(10, "%"); var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right+100) // grr the padding for x axis .attr("height", height + margin.top + margin.bottom) .append("g") .attr("class","main-group") .attr("transform", "translate(" + margin.left + "," + margin.top + ")");; var chart = svg.append("g").attr("transform","translate(100,0)"); var xAxisSelection = chart.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + (height-dominoHeight) + ")") .call(xAxis); var yAxisSelection = chart.append("g") .attr("class", "y axis") .call(yAxis) chart.append("g") .attr("class", "y domino axis") .attr("transform","translate(" + (-10) + "," + (40+height-dominoHeight)+ ")") .call(yAxisDomino); // 1 domino top bottom // 2 domino top bottom one intersections // 3 domino top bottom two intersections var myDomino = dominoGen() .width(function(d,i) {console.log('index',i,d); return d.w; }) .numberOfDominos(function(d,i) { return d.n; }); console.log('prout'); var bars = chart.selectAll(".bar") .data(data,function(d,i) { return d.id}); bars.enter().append("rect") .attr("class", "bar") .attr("x", function(d,i) { console.log('SOME STUFF',d,i);return x(i)+5; }) .attr("width", x.rangeBand()-5) .attr("y", function(d,i) { return y(d.value); }) .attr("height", function(d) { return(height-dominoHeight)-y(d.value); }); var barChart = {}; var dispatch = d3.dispatch(barChart, "hover"); bars.on("mouseover", function(d) { var bb = this.getBoundingClientRect(); d3.select(this) .transition() .duration(200) .ease('cubic-in-out') .attr("fill","gray"); div.html('<span>'+d.value+'</span>') div.transition() .duration(500) .style("opacity", .98) .style("left", (bb.left) + "px") .style("top", (bb.top-35)+window.scrollY+ "px"); dispatch.hover([d]) }) bars.on("mouseout", function(d) { d3.select(this) .transition() .duration(200) .ease('cubic-in-out') .attr("fill","black"); div.transition() .duration(500) .style("opacity", 0); dispatch.hover([]) }); d3.rebind(barChart, dispatch, "on"); barChart.on("hover", function(hovered) { highlightDominos(hovered); }); var enter = chart .append("g") .attr("class","domino-axis") .attr("transform","translate("+0+","+(40+height-dominoHeight)+")") .selectAll("g.dominos") .data(data,function(d){return d.id}) .enter(); var center = (dw) / 2; var r = center / 1.5 var dominosChart = {}; var dominos = enter.append("g") .attr("class", "dominos") .attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" }); //var subsection = n-1; // var heightPerSubSection = w; // var h = heightPerSubSection * n; dominos.append("rect") .attr("fill","white") .attr("stroke","none") .attr("x",0) .attr("y",0) .attr("width",function(d,i){return d.w}) .attr("height",function(d,i){return d.w*d.n}); dominos.append("path") .attr("class", "dominos") .attr("d", myDomino); // data of circe is an array representing lit circle, eg : [0,1,0,0,1] dominos.selectAll("circle").data(function(d){return d.m}) .enter() .append("circle") .attr("cx",function(d,i){ return center}) .attr("cy",function(d,i){ return center + (dw)*i} ) .attr("r", function(d) { return r }) .attr("fill","orange") .attr("visibility",function(d,i) { return d ? "visible" : "hidden"; }) var dispatchDomino = d3.dispatch(dominosChart, "hover"); d3.rebind(dominosChart, dispatchDomino, "on"); dominosChart.on("hover", function(hovered) { console.log('WORKING...'); }); /*svg.selectAll("path.dominos") .data(data) .enter().append("path") .attr("class", "dominos") .attr("d", myDomino) */ console.log('RESULT',result); d3.select('#f_empty').on("click",function() { filterEmptySets(); }) d3.select('#f_full').on("click",function() { toggleFullSet(); }) d3.select('#f_sortFull').on("click",function() { sortFullSet(); }) d3.select('#f_sortEmpty').on("click",function() { sortEmptySet(); }) function zoomed(e) { console.log('gni',y.domain(),xMimickOrdinal.domain()); //d3.select('.x.axis').call(xAxis); // try to retake the domain a = Math.floor(xMimickOrdinal[0]),b = Math.ceiling(xMimickOrdinal[1]); domain = []; for (a;a<b;a++) { domain.push(""+a); } x.domain(domain); d3.select('.y.axis').call(yAxis); d3.select('.y.axis').call(yAxis); //d3.select(this).scale(d3.event.scale); // d3.select(this).attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } console.log('the scale',x,y); /*var zoom = d3.behavior.zoom() .y(y) .x(xMimickOrdinal) .on("zoom", zoomed); svg.call(zoom); */ function highlightDominos(data) { var rects = chart.selectAll("g.dominos"); var dh = rects.data(data,function(d) { return d.id}); dh.selectAll("rect").transition().duration(250).attr("fill","red") dh.exit().selectAll("rect").transition().duration(250).attr("fill","white"); dh.selectAll('circle').transition().duration(750).attr("fill","green"); dh.exit().selectAll('circle').transition().duration(750).attr("fill","orange"); //.data(function(d){console.log('WUT',d);return d.m}); } //TODO _______REFACTOR_____________ function filterEmptySets() { console.log('filter'); var bars = chart.selectAll(".bar") .data(filteredDatas,function(d,i) { return d.id}) bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5}) bars.exit() .transition().duration(1000) .attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects var dominos = chart .selectAll("g.dominos") .data(filteredDatas,function(d,i) { return d.id}) dominos.exit() .transition().duration(1000) .attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" }); dominos.transition().duration(1000) .attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" }); } function sortEmptySet() { console.log('filter'); var sorted = filteredDatas.sort(function(a,b) {return b.value-a.value;}); var bars = chart.selectAll(".bar") .data(sorted,function(d,i) { return d.id}) bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5}) bars.exit() .transition().duration(1000) .attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects var dominos = chart .selectAll("g.dominos") .data(sorted,function(d,i) { return d.id}) dominos.exit() .transition().duration(1000) .attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" }); dominos.transition().duration(1000) .attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" }); } function sortFullSet() { var sorted = data.sort(function(a,b) {return a.value-b.value;}); var bars = chart.selectAll(".bar") .data(sorted,function(d,i) { return d.id}) bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5}) bars.exit() .transition().duration(1000) .attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects var dominos = chart .selectAll("g.dominos") .data(sorted,function(d,i) { return d.id}) dominos.exit() .transition().duration(1000) .attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" }); dominos.transition().duration(1000) .attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" }); } function toggleFullSet() { var bars = chart.selectAll(".bar") .data(data,function(d,i) { return d.id}) bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5}) bars.exit() .transition().duration(1000) .attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects var dominos = chart .selectAll("g.dominos") .data(data,function(d,i) { return d.id}) dominos.exit() .transition().duration(1000) .attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" }); dominos.transition().duration(1000) .attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" }); } // ___________REFACTOR____________________ function dominoGen() { //set defaults accessor var numberOfDominos = function(d,i) {console.log('stuff',i); return d.numberOfSets; }, width = function(d,i) {console.log('index',i); return d.x; }; //returned function to generate circle path function circle(d) { console.log("CALLED WITH",d) var w = d3.functor(width).call(this, d), n = d3.functor(numberOfDominos).call(this, d); console.log(w,h,n); var subsection = n-1; var heightPerSubSection = w; var h = heightPerSubSection * n; var path = ""; for (var i=0; i<=subsection+1;i++) { path = path + "M 0 "+(heightPerSubSection*i)+" H "+w; } path = path + " M 0 0 V "+h; path = path + " M "+w+" 0 V"+h; return path+" z"; } //getter-setter methods circle.numberOfDominos = function(value) { if (!arguments.length) return numberOfDominos; numberOfDominos = value; return circle; }; circle.width = function(value) { if (!arguments.length) return width; width = value; return circle; }; return circle; } d3.svg.dominoGenerator = dominoGen; </script>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js