Tuesday, April 18, 2017

d3.js timeline relationship chart

Leave a Comment

enter image description here I am interested in building this kind of chart. I've started by trying to plot the rectangular timeline - what is the best way of creating this timeline - min/max dates then setting a domain?

//with plot lines -- close example but not locked to timeline http://jsfiddle.net/Qh9X5/10179/

var data = [{   "date": "2012-03-20",   "total": 3 }, {   "date": "2012-03-21",   "total": 8 }, {   "date": "2012-03-22",   "total": 2 }, {   "date": "2012-03-23",   "total": 10 }, {   "date": "2012-03-24",   "total": 3 }, {   "date": "2012-03-25",   "total": 20 }, {   "date": "2012-03-26",   "total": 12 }, {   "date": "2012-03-28",   "total": 17 }];  var margin = {     top: 40,     right: 40,     bottom: 40,     left: 60   },   width = 600,   height = 500;   var y = d3.time.scale()   .domain([new Date(data[0].date), d3.time.day.offset(new Date(data[data.length - 1].date), 1)])   .range([height - margin.top - margin.bottom, 0]);   var yAxis = d3.svg.axis()   .scale(y)   .orient('left')   .tickPadding(1);  var svg = d3.select('#timelines').append('svg')   .attr('class', 'chart')   .attr('width', width)   .attr('height', height)   .append('g')   .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');  var axisArray = [];  //http://stackoverflow.com/questions/22722952/how-can-i-get-the-d3-js-axis-ticks-and-positions-as-an-array  svg.append('g')   .attr('class', 'y axis')   .call(yAxis)   .selectAll(".tick").each(function(data) {     var tick = d3.select(this);     // pull the transform data out of the tick     var transform = d3.transform(tick.attr("transform")).translate;      // passed in "data" is the value of the tick, transform[0] holds the X value     //console.log("each tick", data, transform);      var obj = {       "data": data,       "transform": transform     }      axisArray.push(obj);   });  //console.log("all the points", yAxis.scale().ticks(yAxis.ticks()[0]));  function getRadius(d) {   var count = 2;   var ratio = count * 2.8;    if (count == 1) {     ratio = 10;   }   return ratio; }    var data = [{   "date-start": "2012-03-20",   "date-end": "2012-03-21" }, {   "date-start": "2012-03-22",   "date-end": "2012-03-25" }, {   "date-start": "2012-03-21",   "date-end": "2012-03-24" }];   function getPos(date) {   var trans;   $.each(axisArray, function(index, value) {     var a = value.data;     var b = date;      if (a.getTime() === b.getTime()) {       trans = value.transform;     }   });    return trans; }   var distanceBetween = 70; var path = svg.append("svg:g").selectAll("path")   .data(data)  path   .enter().append("svg:path")   .attr("class", function(d) {     return "link ";   })  path.attr("d", function(d, i) {   var sx = 0;   var tx = 0;    //console.log("d", d);    var posEnd = getPos(new Date(d["date-start"]));   var posStart = getPos(new Date(d["date-end"]));    var sy = posStart[1];   var ty = posEnd[1];    var dx = 0,     dy = getRadius(d) + 15 + (distanceBetween * i),     dr = Math.sqrt(dx * dx + dy * dy);    return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty; }); 

//scale js http://jsfiddle.net/Qh9X5/10168/

//latest js fiddle http://jsfiddle.net/Qh9X5/10165/

  var timeline = svg.select(".timeline").selectAll("rect.slice")     .data(data);    timeline.enter()     .insert("rect")     .attr('fill', "white")     .attr("x", 10)     .attr("y", function(d, i) {       return 5 * i;     })     .attr("width", 20)     .attr("height", 2)     .attr("class", "slice");    timeline     .transition().duration(1000)    timeline.exit()     .remove(); 

1 Answers

Answers 1

I've colored the chart accordingly - but still very keen to find a solution which mimics the rectangle axis style from the design.

enter image description here

http://jsfiddle.net/Qh9X5/10344/

var data = [{   "date": "2012-03-20",   "total": 3 }, {   "date": "2012-03-21",   "total": 8 }, {   "date": "2012-03-22",   "total": 2 }, {   "date": "2012-03-23",   "total": 10 }, {   "date": "2012-03-24",   "total": 3 }, {   "date": "2012-03-25",   "total": 20 }, {   "date": "2012-03-26",   "total": 12 }, {   "date": "2012-03-27",   "total": 17 }];  var margin = {     top: 40,     right: 40,     bottom: 40,     left: 60   },   width = 600,   height = 500;    function colores_google(n) {     var colores_g = ["#df3261", "#4bc2ee", "#251e1c"];     return colores_g[n % colores_g.length];   }   var y = d3.time.scale().range([height - margin.top - margin.bottom, 0]);  y.domain([         d3.min(data, function (c) {              return new Date(c.date);         }),         d3.max(data, function (c) {              return new Date(c.date);         })     ]);     //y.domain([new Date(data[0].date), d3.time.day.offset(new Date(data[data.length - 1].date), 1)])    var yAxis = d3.svg.axis()   .scale(y)   .orient('left')   .tickPadding(1);  var svg = d3.select('#timelines').append('svg')   .attr('class', 'chart')   .attr('width', width)   .attr('height', height)   .append('g')   .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');  var axisArray = [];  //http://stackoverflow.com/questions/22722952/how-can-i-get-the-d3-js-axis-ticks-and-positions-as-an-array  svg.append('g')   .attr('class', 'y axis')   .call(yAxis)   .selectAll(".tick").each(function(data) {     var tick = d3.select(this);     // pull the transform data out of the tick     var transform = d3.transform(tick.attr("transform")).translate;      // passed in "data" is the value of the tick, transform[0] holds the X value     //console.log("each tick", data, transform);      var obj = {       "data": data,       "transform": transform     }      axisArray.push(obj);   });  //console.log("all the points", yAxis.scale().ticks(yAxis.ticks()[0]));  function getRadius(d) {   var count = 2;   var ratio = count * 2.8;    if (count == 1) {     ratio = 10;   }   return ratio; }    var data = [{   "date-start": "2012-03-20",   "date-end": "2012-03-21" }, {   "date-start": "2012-03-22",   "date-end": "2012-03-25" }, {   "date-start": "2012-03-21",   "date-end": "2012-03-23" }];   function getPos(date) {   var trans;   $.each(axisArray, function(index, value) {     var a = value.data;     var b = date;      if (a.getTime() === b.getTime()) {       trans = value.transform;     }   });    return trans; }   var distanceBetween = 70; var path = svg.selectAll("path")   .data(data)   path   .enter().append("path")   .attr("class", function(d) {     return "link";   })   .attr("d", function(d, i) {     var sx = 0;     var tx = 0;      //console.log("d", d);      var posEnd = getPos(new Date(d["date-start"]));     var posStart = getPos(new Date(d["date-end"]));      var sy = posStart[1];     var ty = posEnd[1];      var dx = 0,       dy = getRadius(d) + 15 + (distanceBetween * i),       dr = 10//Math.sqrt(dx * dx + dy * dy);      return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty;   })   .attr('stroke-width', 1)   .attr("stroke", function(d, i) {     console.log("d", i);       return colores_google(i-1);     }) 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment