Javascript D3-刷新图表时重置缩放?
我正在做D3时间尺度/价格尺度的财务图表。图表SVG本身使用zoom()以几何方式平移和缩放数据,并重新绘制轴。图表下方是一个SVG画笔窗格,它以较高的级别显示整个数据集,并允许平移本身。我面临的问题与此小提琴中显示的行为相同(不是我的代码):。刷牙后缩放会导致跳跃行为,因为zoom()从未从刷牙()中拾取更改 Zoom和brush独立工作,但我很难让它们一起工作。当图表被刷的时候,我希望zoom能够检测到这一点,所以下一次图表被缩放时,它会在刷掉的地方重新开始。反之亦然 我已经设法设置了一个同步功能,以便在启动缩放时使画笔正确更新,但我无法使相反的功能正常工作-在导航器中出现画笔时更新图表缩放。我找了好几个小时都没找到。有没有补丁可以修复这个问题?很抱歉代码块太长,但我希望设置上下文会有所帮助 设置代码(为了简洁起见,省略了一些基本变量): 笔刷和缩放功能:Javascript D3-刷新图表时重置缩放?,javascript,svg,d3.js,Javascript,Svg,D3.js,我正在做D3时间尺度/价格尺度的财务图表。图表SVG本身使用zoom()以几何方式平移和缩放数据,并重新绘制轴。图表下方是一个SVG画笔窗格,它以较高的级别显示整个数据集,并允许平移本身。我面临的问题与此小提琴中显示的行为相同(不是我的代码):。刷牙后缩放会导致跳跃行为,因为zoom()从未从刷牙()中拾取更改 Zoom和brush独立工作,但我很难让它们一起工作。当图表被刷的时候,我希望zoom能够检测到这一点,所以下一次图表被缩放时,它会在刷掉的地方重新开始。反之亦然 我已经设法设置了一个同
// zoom - brush synchronizations
function updateBrushFromZoom() {
if ((dateScale.domain()[0] <= minX) && (dateScale.domain()[1] >= maxX)) {
viewport.clear();
} else {
viewport.extent(dateScale.domain());
}
navChart.select('.viewport').call(viewport);
}
function updateZoomFromBrush() {
// help!!
}
function brush() {
var g = d3.selectAll('svg').select('g');
var newDomain = viewport.extent();
if (newDomain[0].getTime() !== newDomain[1].getTime()) {
dateScale.domain([newDomain[0], newDomain[1]]);
var xTransform = fc.utilities.xScaleTransform(initialXScale, dateScale);
// define new data set
var range = moment().range(newDomain[0], newDomain[1]);
var rangeData = [];
for (var i = 0; i < data.length; i += 1) {
if (range.contains(new Date(data[i].startTime*1000))) {
rangeData.push(data[i]);
}
}
// define new mins and maxes
var newMinY = d3.min(rangeData, function (d) {
return d.low;
});
var newMaxY = d3.max(rangeData, function (d) {
return d.high;
});
// set new yScale
priceScale.domain([newMinY, newMaxY]);
var yTransform = fc.utilities.yScaleTransform(initialYScale, priceScale);
// draw new axes on main chart
g.select('.fcChartArea .date.axis')
.call(dateAxis);
g.select('.fcChartArea .price.axis')
.call(priceAxis);
// transform the data to fit new chart viewport
g.select('.series')
.attr('transform', 'translate(' + xTransform.translate + ',' + yTransform.translate+ ')' + ' scale(' + xTransform.scale + ',' + yTransform.scale + ')');
}
else {
// remove transformation
g.select('.series')
.attr('transform', null);
}
updateZoomFromBrush();
}
// Zoom functions
function zoom() {
var g = d3.selectAll('svg').select('g');
// set new xScale
var newDomain = dateScale.domain();
var xTransformTranslate = d3.event.translate[0];
var xTransformScale = d3.event.scale;
// define new data set
var range = moment().range(newDomain[0], newDomain[1]);
var rangeData = [];
for (var i = 0; i < data.length; i += 1) {
if (range.contains(new Date(data[i].startTime*1000))) {
rangeData.push(data[i]);
}
}
// define new max and min
var newMinY = d3.min(rangeData, function (d) {
return d.low;
});
var newMaxY = d3.max(rangeData, function (d) {
return d.high;
});
// set new yScale
priceScale.domain([newMinY, newMaxY]);
var yTransform = fc.utilities.yScaleTransform(initialYScale, priceScale);
// draw new axes on main chart
g.select('.fcChartArea .date.axis')
.call(dateAxis);
g.select('.fcChartArea .price.axis')
.call(priceAxis);
// transform the data to fit new chart viewport
g.select('.series')
.attr('transform', 'translate(' + xTransformTranslate + ',' + yTransform.translate+ ')' + ' scale(' + xTransformScale + ',' + yTransform.scale + ')');
// update SVG navigator
updateBrushFromZoom();
}
fc.utilities.yScaleTransform = function(oldScale, newScale) {
var oldDomain = oldScale.domain();
var newDomain = newScale.domain();
var scale = (oldDomain[1] - oldDomain[0]) / (newDomain[1] - newDomain[0]);
var translate = scale * (oldScale.range()[1] - oldScale(newDomain[1]));
return {
translate: translate,
scale: scale
};
};
fc.utilities.xScaleTransform = function(oldScale, newScale) {
var oldDomain = oldScale.domain();
var newDomain = newScale.domain();
var scale = (oldDomain[1] - oldDomain[0]) / (newDomain[1] - newDomain[0]);
var translate = scale * (oldScale.range()[0] - oldScale(newDomain[0]));
return {
translate: translate,
scale: scale
};
};
在
updateZoomFromBrush()
中,使用zoom.x(dateScale)
将比例重新绑定到缩放行为
这是必需的,因为d3.behavior.zoom()
对传入的标尺的副本进行操作,因此,如果不重新绑定标尺,该行为将不会在brush()
中对标尺的域进行任何更改
请参见
updateZoomFromBrush()
中的此示例,使用zoom.x(dateScale)
将缩放比例重新绑定到缩放行为
这是必需的,因为d3.behavior.zoom()
对传入的标尺的副本进行操作,因此,如果不重新绑定标尺,该行为将不会在brush()
中对标尺的域进行任何更改
请参见
updateZoomFromBrush()
中的此示例,使用zoom.x(dateScale)
将缩放比例重新绑定到缩放行为
这是必需的,因为d3.behavior.zoom()
对传入的标尺的副本进行操作,因此,如果不重新绑定标尺,该行为将不会在brush()
中对标尺的域进行任何更改
请参见
updateZoomFromBrush()
中的此示例,使用zoom.x(dateScale)
将缩放比例重新绑定到缩放行为
这是必需的,因为d3.behavior.zoom()
对传入的标尺的副本进行操作,因此,如果不重新绑定标尺,该行为将不会在brush()
中对标尺的域进行任何更改
看到这个例子可能会有所帮助。我看到了这个问题,但发布的解决方案本身也有问题。可能会有帮助。我看到了这个问题,但发布的解决方案本身也有问题。可能会有帮助。我看到了这个问题,但发布的解决方案本身也有问题。可能会有帮助。我看到了这个问题,但发布的解决方案本身也有问题。
fc.utilities.yScaleTransform = function(oldScale, newScale) {
var oldDomain = oldScale.domain();
var newDomain = newScale.domain();
var scale = (oldDomain[1] - oldDomain[0]) / (newDomain[1] - newDomain[0]);
var translate = scale * (oldScale.range()[1] - oldScale(newDomain[1]));
return {
translate: translate,
scale: scale
};
};
fc.utilities.xScaleTransform = function(oldScale, newScale) {
var oldDomain = oldScale.domain();
var newDomain = newScale.domain();
var scale = (oldDomain[1] - oldDomain[0]) / (newDomain[1] - newDomain[0]);
var translate = scale * (oldScale.range()[0] - oldScale(newDomain[0]));
return {
translate: translate,
scale: scale
};
};