几天前我创建了这个问题,关于当用户选择更改数据顺序时,火花线的排序。答案已解决了这个问题,但仍然需要正确定位突出显示用户放置鼠标的红色圆圈。
这是代码:PLUNKER。
我思考了如何更改代码以在数据排序更改时重新定位火花线圆圈。但我不知道在哪里以及如何更改代码。接下来,我将根据与火花线相关的代码点来说明我的推理。
(1) 这两行代码定义了火花线的域和范围。在数据排序更改时,这些代码似乎不应该被更改。
// domain and range for sparkline lines
var xSpark = d3.scaleLinear().domain([0, numYears-1]).range([0, sparkLength]);
var ySpark = d3.scaleLinear().domain([minYvalue, maxYvalue]).range([itemSize-2, 2]);
(2) 这段代码选择了元素#data-svg-i
(其中i
是火花线),它追加了一个圆圈,将其定位在cx
,cy
上,这取决于xSpark
和ySpark
。
如果1中提到的条件成立(即xSpark
和ySpark
是“固定”的值),那么即使数据顺序发生变化,这段代码也不必更改。
var cells = svg.selectAll('.cell')
.data(data)
.enter()
.append('g')
.append('rect')
.on('mouseover', function(d, i) { // on mouseover rect
// get row, column and value of this rect
var idr = d3.select(this).attr('data-r'); // row
var idc = d3.select(this).attr('data-c'); // column
var value = d3.select(this).attr('data-value');
// highlight this rect
d3.select(this).style('stroke', 'red');
// add red dot to sparkline
d3.select('#data-svg-' + idr)
.append('circle')
.attr('r', 3) // radius
.style('stroke', 'red')
.style('fill', 'red')
.attr('cx', xSpark(idc))
.attr('cy', ySpark(value));
})
(3) 当数据顺序发生变化时,此代码块也无需更改。
line = d3.line()
.x(function(d, i) {
return xSpark(i);
})
.y(function(d) {
return ySpark(d);
})
.defined(function(d) { // for missing (0) data
return d !== 0;
});
(4) 数据应该被更新,但实际上没有更新。 在排序之前,data
包含数据以正确的顺序显示,排序后,data
没有发生变化,但是它应该更改,不是吗?
pos
我认为不应该改变,cx
和 cy
也一样,因为它们取决于 xSpark
/ySpark
和 pos
。
var sparkSvg = d3.select('#sparkline')
.append('svg')
.on('mousemove', function() { // on mousemove svg sparkline canvas
var mouse = d3.mouse(this); // mouse position [x, y]
var r = d3.select(this).attr('data-r'); // number of line
var data = d3.select(this).select('path').data(); // array containing all the data values of that line
var element = document.getElementById('data-path-' + r); // get the right path
var pos = get_data_on_line(data, mouse);
d3.selectAll('.data-svg').selectAll('circle').remove(); // remove old circles
// add new circle
d3.select('#data-svg-' + r)
.append('circle')
.attr('r', 3)
.style('stroke', 'red')
.attr('fill', 'red')
.attr('cx', xSpark(pos[1]))
.attr('cy', ySpark(pos[0]));
})
结论
简言之,我不明白代码应该修改哪一点以及如何修改。 有人能帮助我吗?
编辑1
马克的答案解决了当用户悬停在文件地图矩形上时的问题。
但是当用户悬停在火花线上时,红色圆圈没有定位到正确的位置。 我希望这张图片可以说明问题。
我悬停在与意大利相关的火花线上,圆圈显示在线的上方而不是在线上。 此外,数据似乎混乱了。
编辑2
我测试了这里的代码(马克更新后的代码)。
我添加了一些console.log(d)
,当用户点击行和列标签时:
var rowLabels = svg.append('g')
.attr('class', 'rowLabels')
.selectAll('.rowLabels')
.data(regionsName)
.enter().append('text')
.text(function(d) {
return d;
})
.attr('x', 0)
.attr('y', function(d, i) {
return i * cellSize;
})
.attr('transform', function(d, i) {
return 'translate(-3, 11)';
})
.attr('class', 'rowLabel mono')
.attr('id', function(d) {
return 'rowLabel_' + regionsName.indexOf(d);
})
.attr('label-r', function(d) {
return regionsName.indexOf(d);
})
.attr('font-weight', 'normal')
.style('text-anchor', 'end')
.on('click', function(d, i) {
console.log(d); // <-- ADDDED
rowSortOrder = !rowSortOrder;
sortByValues('r', i, rowSortOrder);
});
// year labels
var colLabels = svg.append('g')
.attr('class', 'colLabels')
.selectAll('.colLabels')
.data(yearsName)
.enter().append('text')
.text(function(d) {
return d;
})
.attr('transform', function(d, i) {
return 'translate(' + (i * cellSize) + ', 2) rotate(-65)';
})
.attr('class', 'colLabel mono')
.attr('id', function(d) {
return 'colLabel_' + yearsName.indexOf(d);
})
.attr('label-c', function(d) {
return yearsName.indexOf(d);
})
.attr('font-weight', 'normal')
.style('text-anchor', 'left')
.attr('dx', '.8em')
.attr('dy', '.5em')
.on('click', function(d, i) {
console.log(d); // <-- ADDDED
colSortOrder = !colSortOrder;
sortByValues('c', i, colSortOrder);
});
错误示例:当用户点击德国,然后是2000年,接着是2002年、2005年、2003年,最后是意大利时,结果如下:
可以看到,由于与Italy
相关的小图表缺失了数据,所以迷你统计图和热力图不正确。
编辑3
我制作了这个 GIF,展示了问题所在:
一开始,德国有两个未知值(分别对应于2000年和2001年)。对应的迷你统计图是正确的。
当你单击Germany
时,数据按降序排列,迷你统计图仍然正确。
然后单击年份2002
,数据按降序排列,行重新排序,迷你统计图也是正确的。
然后单击2005
,数据被排序,迷你统计图正确。
然后单击2003
,一切都再次正确。
最后单击Italy
,图表不再正确。德国有两个缺失的数据,但是在对应的迷你统计图上,这并没有突出显示。相反,这两个缺失的数据出现在了意大利的迷你统计图上。