D3.js 使用圆工具提示创建折线图时出现问题
所以,我试着复制这个。最终的目标是创建一个线条图,其中有一个圆圈跟随鼠标的x位置,并保持在线条上,工具提示显示有关线条上该位置的相关数据。以下是我的代码,我对样式做了一些小的更改,并在线条下方添加了一个填充区域,但我不认为这会对工作方式产生影响:D3.js 使用圆工具提示创建折线图时出现问题,d3.js,D3.js,所以,我试着复制这个。最终的目标是创建一个线条图,其中有一个圆圈跟随鼠标的x位置,并保持在线条上,工具提示显示有关线条上该位置的相关数据。以下是我的代码,我对样式做了一些小的更改,并在线条下方添加了一个填充区域,但我不认为这会对工作方式产生影响: var margin = { top: 20, left: 50, right: 50, bottom: 50 }, wid
var margin = {
top: 20,
left: 50,
right: 50,
bottom: 50
},
width = $element.innerWidth() - margin.left - margin.right,
height = 0.2 * width;
var parseTime = d3.timeParse('%m/%d/%Y');
data.forEach(function(d) {
d.date = parseTime(d.date);
d.price = +d.price;
});
var bisectDate = d3.bisector(function(d) { return d.date; }).left;
var x = d3.scaleTime()
.domain(d3.extent(data, function(d, i) {
return d.date;
}))
.range([0, width]);
var y = d3.scaleLinear()
.domain(d3.extent(data, function(d, i) {
return d.price;
}))
.range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickSizeOuter(0);
var yAxis = d3.axisLeft(y)
.ticks(5)
.tickSizeOuter(0);
var area = d3.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var svg = d3.select('#priceChart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis);
var areaSvg = svg.append('g');
areaSvg.append('path')
.attr('class', 'area')
.attr('d', area(data))
.style('opacity', 0.3);
var lineSvg = svg.append('g');
lineSvg.append('path')
.attr('class', 'line')
.attr('d', line(data));
var focus = svg.append('g')
.style('display', 'none');
focus.append('circle')
.attr('class', 'y')
.style('fill', 'steelblue')
.attr('r', 3);
svg.append('rect')
.attr('width', width)
.attr('height', height)
.style('fill', 'none')
.style('pointer-events', 'all')
.on('mouseover', function() { focus.style('display', null); })
.on('mouseout', function() { focus.style('display', 'none'); })
.on('mousemove', mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select('circle.y')
.attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')');
}
我不知道我做错了什么。但基本上,当我在屏幕的左半部分移动鼠标时,什么也没发生。圆圈出现在图形中的最后一个数据点上,并且从不移动。如果我将鼠标移到图形的右侧,控制台中会出现错误uncaughttypeerror:无法读取未定义的属性“date”
更新
下面是一个表示问题的示例。我提供的代码实际上是一个函数,data和$element都在变量中传递。我已经更改了它们在小提琴中的传递方式,但数据与我正在使用的数据相同。对于使用
d3。平分线
您必须首先对数据数组进行排序
关于这一点,API不是很明确,但您可以在这里阅读:
返回数组中x的插入点以保持排序顺序[…]如果数组已排序,则返回值适合用作拼接的第一个参数。(强调矿山)
因此,在使用d3.Disector之前,这是对数据进行排序的函数:
data.sort(function(a, b) {
return d3.ascending(a.date, b.date)
});
这是你的工作提琴:你能把你的东西放在提琴上吗?(基本上包括html)还有,$element是在哪里定义的?@Deweydeman我编辑了这个问题,加入了一个JSFIDLE,并解释了数据和$element的来源。这太棒了,我自己完全忽略了这一点。非常感谢你的帮助。