#javascript #d3.js #zooming #axis
#javascript #d3.js #масштабирование #ось
Вопрос:
короткая версия: я использую масштабирование по оси и обычное масштабирование. Я объединяю оба вместе, и масштабирование работает нормально. Единственная проблема в том, что перевод работает не так, как я хочу. Перевод по осям не равен 1 к 1. Поведение перевода зависит от масштабного коэффициента обычного масштабирования.
мой статус: у меня есть линейный график с нормальным масштабированием. В дополнение к этому у меня есть масштабирование по оси. Итак, если я нахожусь в области оси Y, я хочу только увеличить ось Y и только перемещать ось Y вокруг. То же самое для оси X.
Для этого я использовал экземпляр d3.zoom и вызвал (zoom) для 3 разных прямоугольников.
- покрывает всю область графика
- распространяется только на ось x
- распространяется только на ось y
Преобразование сохраняется в элементах. Функция масштабирования применяет все 3 разных преобразования масштабирования к масштабу при запуске.
Настройка всего:
graph.zoomXY = d3.zoom()
.scaleExtent([-10, 1000]);
graph.overlayX = graph.g//.select(".axis.x")
.append("rect")
.attr("fill", "rgba(255,0,0,0.5)")
.attr("width", graph.rectWidth)
.attr("height", 15)
.attr("y", graph.rectHeight)
.call(graph.zoomXY);
graph.overlayY = graph.g//.select(".axis.y")
.append("rect")
.attr("fill", "rgba(255,0,0,0.5)")
.attr("width", 150)
.attr("height", graph.rectHeight)
.attr("x", -150)
.call(graph.zoomXY);
//append the rectangle to capture zoom
graph.overlayRect = graph.g.append("rect")
.attr("class", "overlay-rect")
.attr("width", graph.rectWidth)
.attr("height", graph.rectHeight)
.style("fill", "none")
.call(graph.zoomXY)
.on("dblclick.zoom", function() {
resetZoom();
} );
Вычисление масштаба:
function zoomed() {
getZoomedScales();
updateGraph();
}
function getZoomedScales() {
var transformX = d3.zoomTransform(graph.overlayX.node());
var transformY = d3.zoomTransform(graph.overlayY.node());
var transformXY = d3.zoomTransform(graph.overlayRect.node());
graph.yScaleTemp = transformXY.rescaleY(transformY.rescaleY(graph.yScale));
graph.xScaleTemp = transformXY.rescaleX(transformX.rescaleX(graph.xScale));
}
Масштабирование работает нормально. Но на изменение масштаба осей (graph.overlayY и graph.overlayX) влияет коэффициент масштабирования масштабирования, применяемый к graph.overlayRect. Если я изменю порядок, проблема будет просто устранена. Масштабный коэффициент масштабирования осей (graph.overlayY и graph.overlayX) приводит к искажению преобразования масштабирования в graph.overlayRect.
Откройте скрипку и измените масштабирование, находясь над областью графика. Затем наведите курсор мыши на одну из осей. Повторите и посмотрите, как это изменяет перевод.
Вот пример:https://jsfiddle.net/9j4kqq1v /
Комментарии:
1. Итак, я проверил d3.js исходный код и я нашли причину. D3.js v4 сохраняет данные масштабирования в dom-элементе, что вполне очевидно. Но когда запускается onmousedowned и добавляется событие mousemove, оно использует только данные масштабирования, добавленные к этому dom-элементу. Это означает, что другие коэффициенты масштабирования не учитываются. Таким образом, обходной путь состоял бы в том, чтобы применить масштабный коэффициент из xy-zoom к dom-элементам для x-zoom и y-zoom при наведении курсора мыши и отменить его при запуске mosueup. Таким образом, перетаскивание работает должным образом.
2. Благодарим вас за публикацию вашего jsfiddle. Это было очень полезно!!