d3:火灾缩放事件(或模拟缩放事件)

时间:2012-11-06 09:58:41

标签: javascript javascript-events d3.js

当我用鼠标缩放时,将执行以下函数“myZoom”:

myZoom.on('zoom', function() {

    someElement.attr('transform', 'translate(' + d3.event.translate[0] + ',' + d3.event.translate[1] + ') scale(' + d3.event.scale + ')');

....
// redraw axes, which should stay where they are at.
....

}

要在没有鼠标或其他指针设备的情况下模拟缩放,我只需更改上面属性'transform'的值即可。容易。

但问题在于此功能我实际上是重绘轴,其比例会自动重新计算。请参阅d3中的官方文档:

  

zoom.y([Y])

     

指定应自动调整其域的y比例   缩放时。如果未指定,则返回当前的y-scale,即   默认为null。如果以编程方式修改比例的域,   它应该重新分配给缩放行为。

我需要以编程方式进行缩放(可能使用缩放按钮)。如何触发缩放事件,以便自动重新计算轴的比例?

4 个答案:

答案 0 :(得分:6)

程序化缩放在D3库中似乎是一项艰巨的任务,因为D3缩放与鼠标事件密切相关。编程缩放的常见实例是使用滑块控件放大或缩小。令人惊讶的是,我找不到一个如何使用滑块控件进行D3缩放工作的工作示例。在花了一些时间和精力后,我开发了这个工作演示,可以在D3SliderZoom找到。关键点是更改“< g>”的转换属性嵌入在“< svg>”中的SVGElement元素使用滑块抛出的比例值。

function zoomWithSlider(scale) {
    var svg = d3.select("body").select("svg");
    var container = svg.select("g");
    var h = svg.attr("height"), w = svg.attr("width");

    // Note: works only on the <g> element and not on the <svg> element
    // which is a common mistake
    container.attr("transform",
            "translate(" + w/2 + ", " + h/2 + ") " +
            "scale(" + scale + ") " +
            "translate(" + (-w/2) + ", " + (-h/2) + ")");

}

然后必须从滑块的change事件调用此方法,如下所示。

$(function() {
$( "#slider-vertical" ).slider({
    orientation: "vertical",
    range: "min",
    min: 1000,
    max: 10000,
    value: 1000,
    slide: function( event, ui ) {
        zoomWithSlider(ui.value/1000);
    }
});

});

此解决方案比生成伪鼠标滚动事件更优雅。

答案 1 :(得分:2)

我最终自己为新的缩放级别计算新域名。有了这个新域,我可以重绘两个y轴。对于有同样问题的人,我发布了我的代码。这对我的项目来说非常具体,所以可能很难理解。只是为了你的兴趣。

wr.zoomSim = function(sNew) {

    var s = wr.zoom.scale(),
        tx = wr.zoom.translate()[0],
        ty = wr.zoom.translate()[1],
        sReal = sNew / s,
        dtx = wr.width / 2 * (1 - sReal),
        dty = wr.height / 2 * (1 - sReal),
        txNew = sReal * tx + dtx,
        tyNew = sReal * ty + dty,

        a = wr.scaleYBZoom.domain()[0],
        b = wr.scaleYBZoom.domain()[1],
        c = wr.scaleYBZoom.range()[0],
        d = wr.scaleYBZoom.range()[1],
        r = (b-a)/(d-c);

    wr.scaleYBZoom.domain([a + r * ( (c - dty) / sReal - c), a + r * ( (d - dty) / sReal - c)]);

    wr.zoom.scale(sNew);
    wr.zoom.translate([txNew, tyNew]);

    wr.svg2.select('g#bar')
            .attr('transform', 'translate(' + txNew + ',' + tyNew + ') scale(' + sNew + ')');

    wr.svg2.select('g#axisl')
            .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('left'))
        .selectAll('line.tick')
            .attr('x2', wr.width - wr.bar.left - wr.bar.right + 2 * wr.padding);
    wr.svg2.select('g#axisr')
            .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('right'))
        .selectAll('line')
            .remove();

};

答案 2 :(得分:2)

不幸的是@ Debasis的答案对我不起作用,因为我想用zoom behavior来实现这一点,我已经在force layout使用了https://groups.google.com/forum/#!msg/d3-js/qu4lX5mpvWY/MnnRMLz_cnUJ。经过两天的绝望,我终于在这个帖子中找到了解决方案:

{{3}}

function programmaticZoom ($svg, $zoomContainer, zoomBehavior, factor) {

    var width = $svg.attr('width');
    var height = $svg.attr('height');

    var newScale = zoomBehavior.scale() * factor;
    var newX = (zoomBehavior.translate()[0] - width / 2) * factor + width / 2;
    var newY = (zoomBehavior.translate()[1] - height / 2) * factor + height / 2;

    zoomBehavior
      .scale(newScale)
      .translate([newX,newY])
      .event($zoomContainer);
}

答案 3 :(得分:0)

我是通过使用zoomListener完成的。为我做了简单的步骤:

  1. 定义zoomListener: var zoomListener = d3.behavior.zoom();
  2. 调用缩放侦听器 d3.select(该元素 - 即任您需要变焦上).CALL(zoomListener);
  3. 确定缩放步骤。我采取了0.1的步骤。 (使用1.1进行放大,使用0.9进行缩小)
  4. 与当前缩放比例相乘 var newScale = zoomListener.scale()* step;
  5. 设置新的比例值 zoomListener.scale(newScale);