graylog dev
graylog dev

Reputation: 141

How to add dots in D3 graph?

My objective is to draw a graph which has line and dots.

I was able to draw line and dots with zoom and brush but the problem is, when i zoom in or zoom out, the dots are not moving according to zoom.

I am relatively new to D3 graph. Below is the code i have used to plot dots:

    g.selectAll(".dot")
      .data(dots)
      .enter()
      .append("circle")
      .attr("class", "dot")
      .attr("r", 3.5)
      .attr("cx", function(d) { return x(new Date(d.date)); })
      .attr("cy", function(d) { return y(d.price); })
      .on("mouseover", function(d){
        return tooltip.style("visibility", "visible").html("Expected value is: "+d.expected_value + "<br/>"  + "value : "+d.close +"<br/>"  + "deviation is: "+d.deviation_expected)
      })
      .on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
      .on("mouseout", function(){return tooltip.style("visibility", "hidden");});

I have created jsfiddle

Please help.

Upvotes: 0

Views: 1031

Answers (1)

Aravind Cheekkallur
Aravind Cheekkallur

Reputation: 3195

I will describe few basic features you must understand before approaching visualization. As per the fiddle, you have two sets of data that must be plotted across X & Y axis.(Ex: data, dots). Domain for this data sets are different though you need to understand the concept of Domain and range.

d3.scaleLinear() <>

Constructs a new continuous scale with the unit domain [0, 1], the unit range [0, 1], the default interpolator and clamping disabled. Linear scales are a good default choice for continuous quantitative data because they preserve proportional differences. Each range value y can be expressed as a function of the domain value x: y = mx + b.

d3.scaleTime() <>

Constructs a new time scale with the domain [2000-01-01, 2000-01-02], the unit range [0, 1], the default interpolator and clamping disabled.

  • Domain and Range mapping for individual data series
  • Brush and zoom and its invert mapping to the scales
  • Redraw the plots based on new scales.

** Below code snippet is just to explain the brush implementation with out considering the scale for dots. Try it your self to map the logic by reading the documentation Brush Event Example

var data = [{
    "date": "2017-04-22T11:45:00.000Z",
    "total": 731.6047915220261,
    "min": 1.8769680261611938,
    "key_field": "1492861500000",
    "max": 2.7165653705596924,
    "price": 1.8769680261611938,
    "total_count": 315,
    "mean": 2.3225548937207177,
    "count": 315
  },
  {
    "date": "2017-04-01T05:30:00.000Z",
    "total": 708.6527144908905,
    "min": 1.779407262802124,
    "key_field": "1491024600000",
    "max": 2.6382412910461426,
    "price": 1.779407262802124,
    "total_count": 315,
    "mean": 2.249691157113938,
    "count": 315
  },
  {
    "date": "2017-03-31T02:45:00.000Z",
    "total": 700.1026722192764,
    "min": 1.8156663179397583,
    "key_field": "1490928300000",
    "max": 2.587003469467163,
    "price": 1.8156663179397583,
    "total_count": 315,
    "mean": 2.2225481657754806,
    "count": 315
  },
  {
    "date": "2017-03-31T02:30:00.000Z",
    "total": 699.6637561321259,
    "min": 1.8294581174850464,
    "key_field": "1490927400000",
    "max": 2.57082200050354,
    "price": 1.8294581174850464,
    "total_count": 315,
    "mean": 2.221154781371828,
    "count": 315
  },
  {
    "date": "2017-03-31T02:15:00.000Z",
    "total": 702.4780179262161,
    "min": 1.8524492979049683,
    "key_field": "1490926500000",
    "max": 2.628413677215576,
    "price": 1.8524492979049683,
    "total_count": 315,
    "mean": 2.2300889457975117,
    "count": 315
  },
  {
    "date": "2017-03-31T02:00:00.000Z",
    "total": 705.038315653801,
    "min": 1.8353750705718994,
    "key_field": "1490925600000",
    "max": 2.604921340942383,
    "price": 1.8353750705718994,
    "total_count": 315,
    "mean": 2.2382168750914317,
    "count": 315
  },
  {
    "date": "2017-03-31T01:45:00.000Z",
    "total": 701.7422981262207,
    "min": 1.8062856197357178,
    "key_field": "1490924700000",
    "max": 2.5804450511932373,
    "price": 1.8062856197357178,
    "total_count": 315,
    "mean": 2.2277533273848276,
    "count": 315
  },
  {
    "date": "2017-03-31T01:30:00.000Z",
    "total": 706.3951338529587,
    "min": 1.8176854848861694,
    "key_field": "1490923800000",
    "max": 2.584993600845337,
    "price": 1.8176854848861694,
    "total_count": 315,
    "mean": 2.242524234453837,
    "count": 315
  },
  {
    "date": "2017-03-31T01:15:00.000Z",
    "total": 704.2638461589813,
    "min": 1.7730687856674194,
    "key_field": "1490922900000",
    "max": 2.6350574493408203,
    "price": 1.7730687856674194,
    "total_count": 315,
    "mean": 2.235758241774544,
    "count": 315
  },
  {
    "date": "2017-03-31T01:00:00.000Z",
    "total": 703.4522807598114,
    "min": 1.8147484064102173,
    "key_field": "1490922000000",
    "max": 2.5720791816711426,
    "price": 1.8147484064102173,
    "total_count": 315,
    "mean": 2.233181843681941,
    "count": 315
  },
  {
    "date": "2017-03-31T00:45:00.000Z",
    "total": 706.2918384075165,
    "min": 1.7760894298553467,
    "key_field": "1490921100000",
    "max": 2.596073627471924,
    "price": 1.7760894298553467,
    "total_count": 315,
    "mean": 2.2421963124048143,
    "count": 315
  },
  {
    "date": "2017-03-31T00:30:00.000Z",
    "total": 707.0961575508118,
    "min": 1.7756011486053467,
    "key_field": "1490920200000",
    "max": 2.6146974563598633,
    "price": 1.7756011486053467,
    "total_count": 315,
    "mean": 2.2447497065105138,
    "count": 315
  },
  {
    "date": "2017-03-31T00:15:00.000Z",
    "total": 706.1140650510788,
    "min": 1.7976468801498413,
    "key_field": "1490919300000",
    "max": 2.6084225177764893,
    "price": 1.7976468801498413,
    "total_count": 315,
    "mean": 2.2416319525431074,
    "count": 315
  },
  {
    "date": "2017-03-31T00:00:00.000Z",
    "total": 707.5575115680695,
    "min": 1.8497636318206787,
    "key_field": "1490918400000",
    "max": 2.5975091457366943,
    "price": 1.8497636318206787,
    "total_count": 315,
    "mean": 2.2462143224383158,
    "count": 315
  },
  {
    "date": "2017-03-30T23:45:00.000Z",
    "total": 707.9171552658081,
    "min": 1.8517450094223022,
    "key_field": "1490917500000",
    "max": 2.5352094173431396,
    "price": 1.8517450094223022,
    "total_count": 315,
    "mean": 2.247356048462883,
    "count": 315
  },
  {
    "date": "2017-03-30T23:30:00.000Z",
    "total": 707.09266269207,
    "min": 1.8389506340026855,
    "key_field": "1490916600000",
    "max": 2.593708038330078,
    "price": 1.8389506340026855,
    "total_count": 315,
    "mean": 2.244738611720857,
    "count": 315
  },
  {
    "date": "2017-03-30T23:15:00.000Z",
    "total": 708.3666490316391,
    "min": 1.861556053161621,
    "key_field": "1490915700000",
    "max": 2.6234216690063477,
    "price": 1.861556053161621,
    "total_count": 315,
    "mean": 2.2487830127988544,
    "count": 315
  }
  ]
   var dots  =
          [
      {
        "date": "2017-04-22T11:45:00.000Z",
        "total": 731.6047915220261,
        "min": 1.8769680261611938,
        "key_field": "1492861500000",
        "max": 2.7165653705596924,
        "price": 1.8769680261611938,
        "total_count": 315,
        "mean": 2.3225548937207177,
        "count": 315
      },

      {
        "date": "2017-03-31T01:45:00.000Z",
        "total": 701.7422981262207,
        "min": 1.8062856197357178,
        "key_field": "1490924700000",
        "max": 2.5804450511932373,
        "price": 1.7062856197357178,
        "total_count": 315,
        "mean": 2.2277533273848276,
        "count": 315
      },
      {
        "date": "2017-03-31T01:30:00.000Z",
        "total": 706.3951338529587,
        "min": 1.8176854848861694,
        "key_field": "1490923800000",
        "max": 2.584993600845337,
        "price": 1.8176854848861694,
        "total_count": 315,
        "mean": 2.242524234453837,
        "count": 315
      },

      {
        "date": "2017-03-28T18:00:00.000Z",
        "total": 728.67049741745,
        "min": 1.2837289810180664,
        "key_field": "1490724000000",
        "max": 2.706052541732788,
        "price": 1.3837289810180664,
        "total_count": 315,
        "mean": 2.3132396743411108,
        "count": 315
      },
        {
        "date": "2017-03-26T20:00:00.000Z",
        "total": 721.6712145805359,
        "min": 1.8257900476455688,
        "key_field": "1490558400000",
        "max": 2.762291669845581,
        "price": 1.4257900476455688,
        "total_count": 315,
        "mean": 2.291019728827098,
        "count": 315
      },
      {
        "date": "2017-03-28T17:45:00.000Z",
        "total": 726.2018908262253,
        "min": 1.8992395401000977,
        "key_field": "1490723100000",
        "max": 2.7374281883239746,
        "price": 1.8992395401000977,
        "total_count": 315,
        "mean": 2.305402828019763,
        "count": 315
      },
      {
        "date": "2017-03-28T17:30:00.000Z",
        "total": 730.83118724823,
        "min": 1.8232735395431519,
        "key_field": "1490722200000",
        "max": 2.696560859680176,
        "price": 1.3232735395431519,
        "total_count": 315,
        "mean": 2.320099007137238,
        "count": 315
      },
      {
        "date": "2017-03-28T17:15:00.000Z",
        "total": 728.1204907894135,
        "min": 1.8851990699768066,
        "key_field": "1490721300000",
        "max": 2.654668092727661,
        "price": 1.8851990699768066,
        "total_count": 315,
        "mean": 2.3114936215536934,
        "count": 315
      },

      {
        "date": "2017-03-27T02:45:00.000Z",
        "total": 702.2468013763428,
        "min": 1.7651863098144531,
        "key_field": "1490582700000",
        "max": 2.6390604972839355,
        "price": 1.373651863098144531,
        "total_count": 315,
        "mean": 2.229354925004263,
        "count": 315
      },
      {
        "date": "2017-03-27T02:30:00.000Z",
        "total": 700.9137979745865,
        "min": 1.8334004878997803,
        "key_field": "1490581800000",
        "max": 2.620957136154175,
        "price": 1.8334004878997803,
        "total_count": 315,
        "mean": 2.2251231681732904,
        "count": 315
      },
      {
        "date": "2017-03-27T02:15:00.000Z",
        "total": 700.9274371862411,
        "min": 1.8098258972167969,
        "key_field": "1490580900000",
        "max": 2.6065454483032227,
        "price": 1.8098258972167969,
        "total_count": 315,
        "mean": 2.2251664672579086,
        "count": 315
      },
      {
        "date": "2017-03-27T02:00:00.000Z",
        "total": 703.2963272333145,
        "min": 1.7948274354934692,
        "key_field": "1490580000000",
        "max": 2.549198865890503,
        "price": 1.7968274354934692,
        "total_count": 315,
        "mean": 2.2326867531216332,
        "count": 315
      },
      {
        "date": "2017-03-27T01:45:00.000Z",
        "total": 700.4703311920166,
        "min": 1.8429771661758423,
        "key_field": "1490579100000",
        "max": 2.518679141998291,
        "price": 1.348429771661758423,
        "total_count": 315,
        "mean": 2.223715337117513,
        "count": 315
      },
      {
        "date": "2017-03-27T01:30:00.000Z",
        "total": 701.4555011987686,
        "min": 1.7773451805114746,
        "key_field": "1490578200000",
        "max": 2.635554790496826,
        "price": 1.27773451805114746,
        "total_count": 315,
        "mean": 2.2268428609484716,
        "count": 315
      },

      {
        "date": "2017-03-26T20:00:00.000Z",
        "total": 721.6712145805359,
        "min": 1.8257900476455688,
        "key_field": "1490558400000",
        "max": 2.762291669845581,
        "price": 1.48257900476455688,
        "total_count": 315,
        "mean": 2.291019728827098,
        "count": 315
      },
      {
        "date": "2017-03-26T19:45:00.000Z",
        "total": 724.9882735013962,
        "min": 1.80784010887146,
        "key_field": "1490557500000",
        "max": 2.6430490016937256,
        "price": 0.40784010887146,
        "total_count": 315,
        "mean": 2.301550074607607,
        "count": 315
      },


    ]
 
 
  var svg = d3.select("svg"),
      margin = {top: 20, right: 20, bottom: 110, left: 40},
      margin2 = {top: 430, right: 20, bottom: 30, left: 40},
      width = +svg.attr("width") - margin.left - margin.right,
      height = +svg.attr("height") - margin.top - margin.bottom,
      height2 = +svg.attr("height") - margin2.top - margin2.bottom;

  var parseDate = d3.timeParse("%m/%d/%Y %H:%M");
  var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var x = d3.scaleTime().range([0, width]),
      x2 = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      y2 = d3.scaleLinear().range([height2, 0]),
	  dotXScale = d3.scaleTime().range([0, width]),
	  dotYScale = d3.scaleLinear().range([height, 0]);

  var xAxis = d3.axisBottom(x),
      xAxis2 = d3.axisBottom(x2),
      yAxis = d3.axisLeft(y);

  var brush = d3.brushX()
      .extent([[0, 0], [width, height2]])
      .on("brush end", brushed);

  var zoom = d3.zoom()
      .scaleExtent([1, Infinity])
      .translateExtent([[0, 0], [width, height]])
      .extent([[0, 0], [width, height]])
      .on("zoom", zoomed);

      var line = d3.line()
          .x(function (d) { return x(new Date(d.date)); })
          .y(function (d) { return y(d.price); });

      var line2 = d3.line()
          .x(function (d) { return x2(new Date(d.date)); })
          .y(function (d) { return y2(d.price); });

      var clip = svg.append("defs").append("svg:clipPath")
          .attr("id", "clip")
          .append("svg:rect")
          .attr("width", width)
          .attr("height", height)
          .attr("x", 0)
          .attr("y", 0);


      var Line_chart = svg.append("g")
          .attr("class", "focus")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
          .attr("clip-path", "url(#clip)");


      var focus = svg.append("g")
          .attr("class", "focus")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var context = svg.append("g")
      .attr("class", "context")
      .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");

    x.domain(d3.extent(data, function(d) { return new Date(d.date); }));
	dotXScale.domain(d3.extent(dots, function(d) { return new Date(d.date); }));
    y.domain([0, d3.max(data, function (d) { return d.price; })]);
	dotYScale.domain([0, d3.max(dots, function (d) { return d.price; })]);
    x2.domain(x.domain());
    y2.domain(y.domain());


	focus.append("g")
	  .attr("class", "axis axis--x")
	  .attr("transform", "translate(0," + height + ")")
	  .call(xAxis);

	focus.append("g")
	  .attr("class", "axis axis--y")
	  .call(yAxis);

	Line_chart.append("path")
	  .datum(data)
	  .attr("class", "line")
	  .attr("d", line);

	context.append("path")
	  .datum(data)
	  .attr("class", "line")
	  .attr("d", line2);

    context.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height2 + ")")
        .call(xAxis2);

    context.append("g")
        .attr("class", "brush")
        .call(brush)
        .call(brush.move, x.range());

    svg.append("rect")
        .attr("class", "zoom")
        .attr("width", width)
        .attr("height", height)
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .call(zoom);
		
	var tooltip = d3.select("body")
	  .append("div")
	  .style("position", "absolute")
	  .style("z-index", "10")
	  .style("visibility", "hidden")
	  .text("a simple tooltip");
        
	g.selectAll(".dot")
	  .data(dots)
	  .enter()
	  .append("circle")
	  .attr("class", "dot")
	  .attr("r", 3.5)
	  .attr("cx", function(d) { 
		//console.log('---',x(new Date(d.date)))
		return dotXScale(new Date(d.date)); 
		})
	  .attr("cy", function(d) { 
		//console.log(y(d.price));
		return dotYScale(d.price); 
	})
	  .on("mouseover", function(d){
		console.log(d);
		return tooltip.style("visibility", "visible").html("Expected value is: "+d.expected_value + "<br/>"  + "value : "+d.close +"<br/>"  + "deviation is: "+d.deviation_expected)
	  })
	  .on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
	  .on("mouseout", function(){return tooltip.style("visibility", "hidden");});



  function brushed() {
    if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
    var s = d3.event.selection || x2.range();
    x.domain(s.map(x2.invert, x2));
	dotXScale.domain(s.map(x2.invert), x2);
    Line_chart.select(".line").attr("d", line);
    focus.select(".axis--x").call(xAxis);
    svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
        .scale(width / (s[1] - s[0]))
        .translate(-s[0], 0));
	
	g.selectAll(".dot").transition(1000)
            .attr("cx", function (d) { 
			return  dotXScale(new Date(d.date)) })
            .attr("cy", function (d) { 
			//console.log(y(d.price));
			return  dotYScale(d.price) });
  }

  function zoomed() {
    if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
    var t = d3.event.transform;
    x.domain(t.rescaleX(x2).domain());
    Line_chart.select(".line").attr("d", line);
    focus.select(".axis--x").call(xAxis);
    context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
  }

  function type(d) {
    d.date = new Date(d.date);
    d.price = +d.price;
    return d;
  }
.line {
		fill: none;
    stroke: steelblue;
    stroke-width: 2px;
  }

.heading {
	padding-top: 30px;
}

.buttonWidth {
	height: 34px;
	width: 50px;
}

.actiontable {
	width: 36rem;
}

 .line {
        fill: none;
        stroke: steelblue;
        stroke-width: 1.5px;
    }
.zoom {
  cursor: move;
  fill: none;
  pointer-events: all;
}



.area {
  fill: none;
  stroke: #a2dced;
  stroke-width: 2;
  clip-path: url(#clip);
}

.zoom {
  cursor: move;
  fill: none;
  pointer-events: all;
}

rect.selection
{
	fill:green;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="500"></svg>

Upvotes: 1

Related Questions