D3: remap mousewheel to be panning gesture instead of zoom gesture

后端 未结 2 1273
不思量自难忘°
不思量自难忘° 2021-01-07 04:06

By default, when you create a new zoom behavior in D3, it maps the mousewheel to control zoom level. You can also click and drag to pan the chart if it\'s larger than the c

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-07 04:11

    Ok, here we go: Based on Lars' comment, we can specify event handler for mousewheel event. As shown in the answer, we start by mapping wheel.zoom event to a custom handler pan

    selection.call(zoomer)
          .on("wheel.zoom",pan) // handler function for mousewheel zoom
    

    Second, we need to define the pan gesture, which is basically a translate in x and/or y direction.

    function pan() {
      svg.attr("transform", "translate(" + [dx,dy] + ")");
    }
    

    We also need to quantify the movement in both directions, and relate it to mousewheel movement. By inspecting the details of MouseWheel event, we find two useful attributes deltaX and deltaY, indicating how much the mousewheel moved in each direction.

    The final pan function is as follows

    function pan() {
        current_translate = d3.transform(svg.attr("transform")).translate;
        dx = d3.event.wheelDeltaX + current_translate[0];
        dy = d3.event.wheelDeltaY + current_translate[1];
        
      svg.attr("transform", "translate(" + [dx,dy] + ")");
      d3.event.stopPropagation();
    }
    

    Here is a working fiddle and bl.ock also modifying Mike's geometric zoom example.

    Cross-browser support:

    It seems that mousewheel events differs between browsers. For Safari and Firefox support, you need to add the following:

    selection.call(zoomer)
      .on("wheel.zoom",pan) 
      .on("mousewheel.zoom", pan)
      .on("DOMMouseScroll.zoom", pan)
    

    Also, the interpretation of wheelDelta is reversed in Firefox. wheelDelta can be fixed by this function

    function crossWheelDelta()
      // cross-browser wheel delta
      var e = window.event || e; // old IE support
      return Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
    }
    

提交回复
热议问题