CODEXE

D3 Line Chart Hover Scatter Plot


                 .tick line{
            			opacity: 0.2;
		  }
		.line{
		  fill: none;
		  stroke: steelblue;
		  stroke-width: 1.5px;
		}
		.line:hover{
			stroke-width:2.5px;
		}
		.hover-rect{
			fill:none; 
			pointer-events: all;
		}
		.hover-line {
		  stroke: steelblue;
		  stroke-width: 1px;
		  stroke-dasharray: 3,3;
		}
            	

    var margin = {top: 20, right: 20, bottom: 50, left: 70};
    var width = 500 - margin.left - margin.right;
    var height = 200 - margin.top - margin.bottom;
	
	//add svg with margin !important
	//this is svg is actually group
	var svg = d3.select("#diagram").append("svg")
				.attr("width",width+margin.left+margin.right)
				.attr("height",height+margin.top+margin.bottom)
				.append("g")  //add group to leave margin for axis
				.attr("transform","translate("+margin.left+","+margin.top+")");
	
	
	//the code above should be same
	
	var dataset = [[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
                [410, 12], [475, 44], [25, 67], [85, 21], [220, 88]];
	//for each d, d[0] is the first num, d[1] is the second num
	//set y scale
	var yScale = d3.scaleLinear().rangeRound([0,height]).domain([d3.max(dataset,function(d){return d[1];}),0]).nice();//show negative
	//add x axis
	var xScale = d3.scaleLinear().rangeRound([0,width]).domain([0,d3.max(dataset, function(d){return d[0];})]).nice();//scaleBand is used for  bar chart
	
	//sort x
	dataset.sort(function(a,b){
		if(a[0]< b[0]){
			return -1;
		}
		else{
			return 1;
		}
	})
	
	var line = d3.line()
				.x(function(d){return xScale(d[0]);})
				.y(function(d){return yScale(d[1]);})
				.curve(d3.curveLinear);//default is d3.curveLinear
	
	//add line to svg. use path-->to know svg path
	//must add css class line, you can try to remove it and see the result
	var linePath = svg.append("path").attr("class","line").attr("d",line(dataset));
	
	//add x and y axis
	var yAxis = d3.axisLeft(yScale).tickSize(-width);
	svg.append("g").call(yAxis);
	

	var xAxis = d3.axisBottom(xScale);/*.tickFormat("");remove tick label*/
	svg.append("g").call(xAxis).attr("transform", "translate(0,"+height+")");
	
	//add label for x axis and y axis
	svg.append("text").text("Y Label")
		.attr("x",0-height/2)
		.attr("y",0-margin.left)
		.attr("dy","1em")
      	.style("text-anchor", "middle")
		.attr("transform","rotate(-90)");
	svg.append("text").text("X Label")
		.attr("x",width/2)
		.attr("y",height+margin.bottom)
      	.style("text-anchor", "middle");
	//add scatter plot
	var hoverGroup = svg.append("g").attr("class",".hover-group");	
	var circles = hoverGroup.selectAll("g").data(dataset).enter().
	append("g").attr("class","hover").append("circle").attr("visibility","hidden");
	circles.attr("cx",function(d){
			  return xScale(d[0]);//i*(width/dataset.length);
			  })
	.attr("cy",function(d){
		return yScale(d[1]);
	})//for bottom to top
	.attr("r", 3);
	circles.attr("fill",function(d){
		return "orange";
	});
		
	var xLine = hoverGroup.append("line")
	.attr("class","hover-line")
	.attr("x1",0)
	.attr("x2",0)
	.attr("y1",0)
	.attr("y2",height)
	.attr("visibility","hidden");
	
	//add rect for mouse event
	var bisectX = d3.bisector(function(d) { return d[0]; }).left;
	d3.select("svg").append("rect")
		.attr("width",width).attr("height",height)
		.attr("class","hover-rect")
		.attr("transform","translate("+margin.left+","+margin.top+")")
		.on("mousemove",function(e){
			xLine.attr("visibility","visible");
			circles.attr("visibility","hidden");
			var x = xScale.invert(d3.mouse(this)[0]);
			var i = bisectX(dataset, x, 1);//0 is the first point
			i=i==dataset.length?dataset.length-1:i;
		
			var data = (dataset[i][0]-x)>(x-dataset[i-1][0])?dataset[i-1]:dataset[i];

			circles.each(function(d){//linear search used for small data set
				if(this.getAttribute("cx")==xScale(data[0])){
					this.setAttribute("visibility","visible");
				}
			});
			
			xLine.attr("transform", "translate(" + xScale(data[0]) + ",0)");
			xLine.attr("y1",yScale(data[1]));
			 
		 })	
		.on("mouseout",function(e){
			xLine.attr("visibility","hidden");
			circles.attr("visibility","hidden");
		});