2016-09-21 102 views
5

我正在使用d3.js v4。我目前正在实施程序化缩放。这Panning and Zooming Tutorial已经非常有帮助。我的缩放与滚动轮一起工作,但我想创建按钮进行缩放。我知道缩放和平移有什么必要,是翻译[tx, ty]和比例因子k。我正在为我的X轴使用时间刻度。我设法得到tx和比例因子k,在x轴上获得p1 (point 1)p2(point 2)的像素值,然后使用这些值得到k(比例因子)。喜欢这样:W/Programmatic Zoom v4

var k = 500/(xScale(p2) - xScale(p1)); //500 is desired pixel diff. between p1 and p2, and xScale is my d3.scaleTime() accessor function. 
// for this zoom i just want the first value and last value to be at scale difference of the entire width. 

然后,我计算出这个TX:

var tx = 0 - k * p1; 

然后馈入一个d3.zoomIdentity()和重新调整我的xdomain。我创建了一个缩小的按钮。问题是当我放大,然后尝试使用按钮缩小,它缩小,但收缩的X轴。我似乎无法找出为什么它缩小了X轴,而不是正确缩小。

我的jsfiddle

https://jsfiddle.net/codekhalifah/Lmdfrho7/2/

我已经试过

我的代码

后滚轮缩放应用运行此功能:

function zoomed() { 
     if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush 
var t = d3.event.transform; 
console.log(t); 
console.log(xScale.domain()); 
xScale.domain(t.rescaleX(x2).domain()); 
usageAreaPath.attr("d", area); 
usageLinePath.attr('d',line); 
weatherAreaPath.attr('d',weatherChart.area); 
focus.select(".axis--x").call(xAxis); 
focus.selectAll('.circle') 
    .attr('cx', function(d) { return xScale(getDate(d)); }) 
    .attr('cy', function(d) { return yScale(d.kWh); }) 
    .attr("transform", "translate(0," + 80 + ")"); 

     ... other non related items 
    } 

变焦正常工作,但放大,然后手动试图放大正常位置,我想以后。 我的手动变焦按钮功能

function programmaticZoom(){ 
var currDataSet = usageLinePath.data()[0], //current data set 
     currDataSetLength = currDataSet.length,//current data set length 
     x1 = currDataSet[0].usageTime, //getting first data item 
     x2 = currDataSet[currDataSetLength-1].usageTime, //2nd data item 
     x1px = xScale(moment(x1)), //Get current point 1 
     x2px = xScale(moment(x2)); // Get current point 2 

     // calculate scale factor 
     var k = width/(x2px - x1px); // get scale factor 
     var tx = 0 - k * x1px; // get tx 
     var t = d3.zoomIdentity.translate(tx).scale(k); //create zoom identity 

     xScale.domain(t.rescaleX(window.x2).domain()); 
     usageAreaPath.attr("d", area); 
     usageLinePath.attr('d',line); 
     weatherAreaPath.attr('d',weatherChart.area); 
     focus.select(".axis--x").call(xAxis); 
     focus.selectAll('.circle') 
      .attr('cx', function(d) { return xScale(getDate(d)); }) 
      .attr('cy', function(d) { return yScale(d.kWh); }) 
      .attr("transform", "translate(0," + 80 + ")"); 

} 
+0

只是要清楚;你想让你的变焦按钮始终放大回到默认的初始视图? – Hamms

+0

@Hamms嗯,我想实际上能够放大到不同的级别。这只是我的第一个测试级别。但在Timescale上,我想从几个月的视图缩放到周视图,一天缩小到15分钟。我的第一个测试级别是回到看到几个月。 – inspired

+0

@Hamms有什么想法? – inspired

回答

3

我一直在看这一会儿了,我得到了它排序工作,有一件事我想不通,但是你也许能因为你似乎比我更熟悉d3。在您的programmaticZoom()函数中,我注意到tx是图的起始位置的偏移量,而k是比例尺。利用这一点,我换了块:

var k = width/(x2px - x1px); // get scale var tx = 0 - k * x1px; // get tx var t = d3.zoomIdentity.translate(tx).scale(k);

var k = 1; var t = d3.zoomIdentity.scale(k);

首先,当k = 1.0,图形将适合在窗口完美。我相信将k设置为原来的值的原因是错误的是,当您将k的值增加到k > 1.0时,它会将图形的宽度拉伸到屏幕之外。图表上的内容必须重新调整,以便尽可能在图表上占用尽可能多的空间,同时仍在屏幕范围内。使用k < 1(这与width/(x2px - x1px);发生的情况相同),图表缩小为小于屏幕大小。像这样重新调整只会使图形的内容在图内占据最大值,但由于图形比屏幕小,因此它将被重新调整以适应缩小的图形并且显示为比屏幕更小。

我摆脱了tx完全是因为它抵消了图表的起始位置。当图形放大时,它的宽度被拉伸过屏幕。在这里偏移是有意义的,因为您需要使偏移等于您想要开始查看图形的位置,并允许您不需要的部分保持离开屏幕。如果您一直缩小图形,图形为屏幕大小的,所以偏移会导致图形不在屏幕的开头处开始,而是将其一部分从屏幕的开始处移开屏幕。在你的情况下,k已经缩小了图形,偏移会导致缩小的图形出现在屏幕中间。但是如果图形没有缩小,偏移量会将图形的一部分从屏幕上移开。

通过改变,缩小按钮出现工作,但仍然有问题。在zoomed()函数中,您设置了var t = d3.event.transform;d3.event.transform包含的值为k, x, and y,当完全缩小时需要分别为1, 0, and 0。但我不能在programmaticZoom()函数中更改这些值,因为d3.event.transform只在触发事件(特别是鼠标滚轮)后才存在。如果仅在单击缩放按钮时才能将这些值设置为k = 1, x = 0, y = 0,则应该完全解决问题。

希望这有助于一些人,我对d3不是很熟悉,但是这应该可以解决您的大部分问题,并希望能够告诉您发生了什么问题。