【问题标题】:D3 v4 Zoom x-Axis Zooming and Panning IssueD3 v4 Zoom x 轴缩放和平移问题
【发布时间】:2018-01-23 18:02:12
【问题描述】:

我使用 D3 v4 创建了一个图表,它允许 x 轴平移和缩放。我在平移和缩放时以不同方式更新图表,以减少我们重新生成图表的次数。

至于平移

当用户向左或向右平移时,我只需更新transform 属性:

path.attr("transform", d3.event.transform).

效果很好。

至于缩放

当用户缩放时,我会重新缩放域并重新生成图形,以实现所需的行为:

t = d3.event.transform;
xScale.domain(t.rescaleX(x2).domain()); //update xScale domain

xAxis =d3.axisBottom(xScale)...
focus.select(".axis--x").call(xAxis);
usageAreaPath.attr("d", area); //area being a reference to the generator
usageLinePath.attr('d',line); //line being the name of the generator

问题是,执行缩放后平移或平移后缩放会导致图形跳转到不同的缩放级别。我不确定我做错了什么,或者如何在缩放/平移后重新绑定比例以更新正确的比例,但我在下面附上了一个 JSBIN:

http://jsbin.com/webowajola/edit?js,output

【问题讨论】:

  • 在 D3 中,缩放处理平移。所以,你只需要.on("zoom", redraw);
  • @GerardoFurtado 如果我通过重绘处理平移,我将重新生成图形。我不想重新生成图形,我只想根据平移平移图形,即usageAreaPath.attr("transform", d3.event.transform); 但如果有缩放,我想使用重绘内容。即usageAreaPath.attr("d", area); usageLinePath.attr('d',line);
  • @GerardoFurtado 很抱歉让您感到困惑,我的问题清楚吗?
  • 我们应该如何在你的 jsbin 中看到问题?我们怎样才能平移?我们如何缩放?
  • 首次加载图表时,可以通过上下滚动鼠标滚轮进行上下缩放。

标签: javascript d3.js


【解决方案1】:

您的代码有两个单独的问题:

1.翻译

你用错了.attr("transform", "translate( 0, 80)")。从您的<path><circle>、轴和区域中删除所有.attr("transform", "translate(0," + 80 + ")"),并像这样设置偏移量:

// Usage x-axis
var gX = focus.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + (height + margin.top) + ")")
    .call(xAxis);

// Focus Viewpoint
var focus = svg.append("g")
    .attr("class", "focus")
    .attr('transform', "translate(" 
        + margin.left + "," + (margin.top + 80) 
        + ")"
     );

这样做,整个图表在<g>中一起向下移动。

2。 panRight()

您正在移动圆圈和线条两次:第一次使用新刻度,第二次使用.attr("transform", d3.event.transform)。所以只需删除以下三行

usageAreaPath.attr("transform", d3.event.transform);
usageLinePath.attr("transform", d3.event.transform);
circles.attr("transform", d3.event.transform);

Here the working jsbin

编辑

我刚刚意识到,缩放功能根本不起作用。在平移期间一直调用重绘函数(也在我的解决方案中)。因此平移执行两次。如果缩放函数中的“if 语句”有效,则 panRight() 函数将是必要的。所以专注于这个 if/else 语句。一种选择可能是区分鼠标滚轮和拖动事件,例如 if(d3.event.sourceEvent.toString() === "[object MouseEvent]")。因此在平移过程中不会调用重绘函数,但仍然存在一些缩放问题。也许this 能帮上忙。

【讨论】:

    【解决方案2】:

    我不知道你的目标是什么,我认为上面的答案解决了你的问题,也许你只是没有停止活动,如果你想停止活动,请使用 d3.event.defaultPrevented()

        function panRight(){
              d3.event.defaultPrevented()//use it so it will reset the event
              console.log('panRight',d3.event.transform);
    
              var new_xScale = d3.event.transform.rescaleX(x2)
              gX.call(xAxis.scale(new_xScale));
              usageAreaPath.attr("transform", d3.event.transform);
              usageLinePath.attr("transform", d3.event.transform);
              circles.attr("transform", d3.event.transform);
            }
    //the result is normal ordinary chart
    

    但如果你在 redraw() 上不加注释 d3.event.defaultPrevented(),结果是一张奇怪的图表

    function redraw(){
      //d3.event.defaultPrevented()
      var domain, 
      minBuffer, 
      maxBuffer, 
      panDelta1,
      panDelta2,
      t;
    
      t = d3.event.transform;
      console.log('redraw',d3.event.transform);      
      // console.log(t.rescaleX(x2).domain());
      // console.log(xScale.domain());
      //d3.event.defaultPrevented()
      xScale.domain(t.rescaleX(x2).domain());
    
      xAxis = d3.axisBottom(xScale).tickSize(0).tickFormat(d3.timeFormat('%b'));
      focus.select(".axis--x").call(xAxis);
    
      usageAreaPath.attr("d", area);
    
      usageLinePath.attr('d',line);
    
    
    
      //d3.event.defaultPrevented()
      focus.selectAll('.circle')
          .attr('cx', function(d) { return xScale(getDate(d)); })
          .attr('cy', function(d) { return yScale(d.kWh); })
          .attr("transform", "translate(0," + 80 + ")");
    
    
    }
    

    【讨论】:

      【解决方案3】:

      如果您在平移和缩放时以不同方式更新图表以减少我们重新生成图表的次数,只需在 zoomed 函数中添加检查,如下所示,

      function zoomed(){
          if(d3.event.transform.x !== 0 &&  d3.event.transform.y !== 0){
              redraw();
          }
      }
      

      Here is the link to the updated working jsbin.

      希望它能解决您的图形再生问题。

      【讨论】:

      • 我不想用重绘来处理平移,如果有平移,我不想重新生成图形,即usageAreaPath.attr("d", area); usageLinePath.attr('d',line);
      • 很抱歉给您带来了困惑,我问的清楚吗?
      猜你喜欢
      • 2018-12-03
      • 2017-11-02
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多