问答详情
源自:-

怎么用d3画跟随鼠标的十字线(当前点的横纵坐标),并且显示当前点的值

我现在已经画出了带坐标的曲线图,数据是后台加载来的 现在想要实现一个功能就是鼠标画上的时候可以有一条跟随鼠标的十字线,分别从x和y轴拉过来,并且显示当前的xy坐标,并在一个方框内显示当前点的其他描述内容。类似这样的。http://img.mukewang.com/5788494200010cbd05050228.jpg

提问者::D 2016-07-15 10:24

个回答

  • 夏浅浅Sarah
    2016-10-10 15:20:43
    已采纳

    效果图:

    http://img.mukewang.com/57fb41400001cf7e07610358.jpg

    代码:

    D3.html

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<title>D3</title>
    	<link rel="stylesheet" href="css/D3.css">
    </head>
    <body>
    	<div id="container">	
    	<div id="dialog"></div>	
    	</div>
    	<script src="http://d3js.org/d3.v3.js"></script>
    	<script src="js/D3_line_point.js"></script>
    
    </body>
    </html>

    D3.css

    body {
    	font: 10px sans-serif;
    }
    path {
    	fill: none;
    	stroke: #4682B4;
    	stroke-width: 2;
    }
    .domain, .tick line {
    	stroke: gray;
    	stroke-width: 1;
    }
    .circle {
    	fill: white;
    	stroke: steelblue;
    	stroke-width: 2px;
    }
    .area {
    	fill: steelblue;
    	stroke: none;
    	opacity: 0.1;
    }
    .zeroline {
    	fill: none;
    	stroke: red;
    	stroke-width: 0.5px;
    	stroke-dasharray: 5 5;
    }
    .zerolinetext {
    	fill: red;
    }
    .overlay {
    	fill: none;
    	stroke: none;
    	pointer-events: all;
    }
    .focusLine {
    	fill: none;
    	stroke: steelblue;
    	stroke-width: 0.5px;
    }
    .focusCircle {
    	fill: red;
    }
    #dialog{
    	width: 160px;
    	height: 60px;
    	background-color: #4682B4;
    	position: fixed;
    	top:50px;
    	left:600px;
    	opacity: 0;
    	line-height: 20px;
    }


    D3_line_point.js

    var data = [];
    var currentValue = 100;
    var random = d3.random.normal(0, 20.0);
    
    for (var i = 0; i < 100; i++) {
    	var currentDate = new Date();
    	currentDate.setDate(currentDate.getDate() + i);
    
    	data.push([currentDate, currentValue]);
    	currentValue = currentValue + random();
    }
    
    
    var drawLineGraph = function(containerHeight, containerWidth, data, yLabel, warnLine) {
    
    	var svg = d3.select("body").append("svg")
    		.attr("width", containerWidth)
    		.attr("height", containerHeight);
    
    	var margin = {
    		top: 50,
    		left: 50,
    		right: 50,
    		bottom: 50
    	};
    
    	var height = containerHeight - margin.top - margin.bottom;
    	var width = containerWidth - margin.left - margin.right;
    
    	var xDomain = d3.extent(data, function(d) {
    		return d[0];
    	})
    	var yDomain = d3.extent(data, function(d) {
    		return d[1];
    	});
    
    	var xScale = d3.time.scale().range([0, width]).domain(xDomain);
    	var yScale = d3.scale.linear().range([height, 0]).domain(yDomain);
    
    	var xAxis = d3.svg.axis().scale(xScale).orient('bottom');
    	var yAxis = d3.svg.axis().scale(yScale).orient('left');
    
    	var line = d3.svg.line()
    		.x(function(d) {
    			return xScale(d[0]);
    		})
    		.y(function(d) {
    			return yScale(d[1]);
    		});
    
    	var area = d3.svg.area()
    		.x(function(d) {
    			return xScale(d[0]);
    		})
    		.y0(function(d) {
    			return yScale(d[1]);
    		})
    		.y1(height);
    
    	var g = svg.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
    
    	g.append('path')
    		.datum(data)
    		.attr('class', 'area')
    		.attr('d', area);
    
    	g.append('g')
    		.attr('class', 'x axis')
    		.attr('transform', 'translate(0, ' + height + ')')
    		.call(xAxis);
    
    	g.append('g')
    		.attr('class', 'y axis')
    		.call(yAxis)
    		.append('text')
    		.attr('transform', 'rotate(-90)')
    		.attr('y', 6)
    		.attr('dy', '.71em')
    		.attr('text-anchor', 'end')
    		.text(yLabel);
    
    	g.append('path')
    		.datum(data)
    		.attr('class', 'line')
    		.attr('d', line);
    
    	g.selectAll('circle').data(data).enter().append('circle')
    		.attr('cx', function(d) {
    			return xScale(d[0]);
    		})
    		.attr('cy', function(d) {
    			return yScale(d[1]);
    		})
    		.attr('r', 3)
    		.attr('class', 'circle');
    
    	// focus tracking
    
    	var focus = g.append('g').style('display', 'none');
    
    	focus.append('line')
    		.attr('id', 'focusLineX')
    		.attr('class', 'focusLine');
    	focus.append('line')
    		.attr('id', 'focusLineY')
    		.attr('class', 'focusLine');
    	focus.append('circle')
    		.attr('id', 'focusCircle')
    		.attr('r', 5)
    		.attr('class', 'circle focusCircle');
    
    	var bisectDate = d3.bisector(function(d) {
    		return d[0];
    	}).left;
    
    	g.append('rect')
    		.attr('class', 'overlay')
    		.attr('width', width)
    		.attr('height', height)
    		.on('mouseover', function() {
    			focus.style('display', null);
    			d3.select('#dialog')
    			.style('opacity',0);
    		})
    		.on('mouseout', function() {
    			focus.style('display', 'none');
    			d3.select('#dialog')
    			.style('opacity',0);
    		})
    		.on('mousemove', function() {
    			var mouse = d3.mouse(this);
    			var mouseDate = xScale.invert(mouse[0]);
    			var i = bisectDate(data, mouseDate); // returns the index to the current data item
    
    			var d0 = data[i - 1]
    			var d1 = data[i];
    			// work out which date value is closest to the mouse
    			var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;
    
    			var x = xScale(d[0]);
    			var y = yScale(d[1]);
    
    			focus.select('#focusCircle')
    				.attr('cx', x)
    				.attr('cy', y);
    			focus.select('#focusLineX')
    				.attr('x1', x).attr('y1', yScale(yDomain[0]))
    				.attr('x2', x).attr('y2', yScale(yDomain[1]));
    			focus.select('#focusLineY')
    				.attr('x1', xScale(xDomain[0])).attr('y1', y)
    				.attr('x2', xScale(xDomain[1])).attr('y2', y);
    
    			d3.select('#dialog')
    				//.attr('transform', 'translate(' + x + ',' + y + ')')
    				//.attr('text-anchor', 'middle')
    				.style('opacity','0.7')
    				.text(d[0]+' '+d[1]);
    
    		});
    
    	// warn line
    
    	if (warnLine && yDomain[0] < warnLine.lineValue && yDomain[1] > warnLine.lineValue) {
    		g.append('line')
    			.attr('x1', xScale(xDomain[0]))
    			.attr('y1', yScale(warnLine.lineValue))
    			.attr('x2', xScale(xDomain[1]))
    			.attr('y2', yScale(warnLine.lineValue))
    			.attr('class', 'zeroline');
    		g.append('text')
    			.attr('x', xScale(xDomain[1]))
    			.attr('y', yScale(warnLine.lineValue))
    			.attr('dy', '1em')
    			.attr('text-anchor', 'end')
    			.text(warnLine.label)
    			.attr('class', 'zerolinetext');
    	}
    };
    
    drawLineGraph(400, 800, data, "Intensity", {
    	lineValue: 200,
    	label: "OMG!"
    });