Размещение круга над искровой линией, когда пользователь меняет порядок данных
Я создал этот вопрос несколько дней назад относительно упорядочения искровых линий, когда пользователь решает изменить порядок данных. Ответ решил проблему, но остается правильное расположение красных кругов, которые выделяют, где пользователь помещает мышь.
Это код: 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
Что 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
содержат данные в правильном порядке, в котором они отображаются, после упорядочения 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
Отметка ответа решает проблему, когда пользователь наводил курсор на прямоугольник filemap.
Но когда пользователь нависает над искровыми линиями, красные круги не располагаются в правильном положении. Я надеюсь, что этот образ может прояснить, в чем проблема.
Я завис над искровой линией, связанной с Италией, и круг отображается не на линии, а выше. Кроме того, данные, похоже, перепутаны.
EDIT 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
и график больше не верен. В Германии есть два недостающих данных, но из соответствующей искровой линии это не подсвечивается. Вместо этого две отсутствующие данные находятся на искровой линии Италии.
Ответы
Ответ 1
Это новая и четкая концепция визуализации. Если я правильно понимаю, нам нужно получить полное выравнивание между прямоугольниками и искровыми линиями, накидками и всплывающими подсказками, независимо от сортировки. Для моего ответа я буду использовать plunkr, на который вы ссылаетесь сначала (а не на версию Mark). Если я правильно понял вопрос, тогда нужно решить пять вопросов:
- Сортировка по вертикали стирает базу данных, используемую в наведении курсора мыши
Во-первых, при сортировке вертикальных линий svg вертикально вы оцениваете новые данные - это переписывание дочерних элементов пути, поэтому после сортировки по вертикали мышь не работает при зависании над искровыми линиями (круг обнимает верхнюю часть каждого svg). См. Этот упрощенный пример, например:
var div = d3.select("body").append("div");
div.append("p").datum("hello").text(function(d) { return d; });
div.datum("new datum").select("p").text(function(d) { return d; });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>