如何在D3.js v.4.x中设置缩放系数?

时间:2016-11-19 19:22:36

标签: javascript html d3.js svg d3.js-v4

我有一个svg,我通过D3.js实现了缩放。 使用鼠标滚轮时,我对缩放系数不满意。 如何调整缩放系数?

我制作了一个JSfiddle,其中举例说明了我如何实现缩放。

我认为我需要这样的东西,但这是错误的:

zoom.scaleBy()

我试图让我的问题更清楚一点:

我想设置一个因子,它可以作为一个鼠标滚轮旋转的缩放系数。 带图片的插图:

没有缩放的SVG: Normal SVG

一次鼠标轮转动后: After one mousewheel revolution.

在一次鼠标革命革命之后我想拥有什么: But I want some steps in between (like that)

我知道这在旧版本的D3.js中是如何工作的,但有人可以帮助我使用当前版本吗?

1 个答案:

答案 0 :(得分:3)

你在JS小提琴中非常接近!

问题的症结在于,在调用事件回调时,缩放因子k会自动更新。这里的目标是当我们从之前的k(old_k)更改为新k时,我们需要缩放更改delta,然后重新应用它以获得新的k值。

所以执行此操作的代码更改如下...

  1. 跟踪旧k值

    var old_k = 1;
    
  2. 计算delta k

    var delta = d3.event.transform.k - old_k
    
  3. 使用带有缩放delta的转换进行更新!

    d3.event.transform.k = old_k + zoomFactor*delta
    
  4. 重新应用转换

    svg.attr("transform", d3.event.transform);
    
  5. 为下一个活动保存新k

    old_k = d3.event.transform.k
    
  6. var zoomFactor = .7;一起玩,看看它是否有效。

    
    
    console.clear()
    //movement and controls
    var stepLR = 30;
    var controller;
    var speed = 0.007;
    
    //pendulum vertical
    var cx = 609, cy = 0;
    var radius = 350; // cm
    var g = 981; // cm/s^2
    var angle = Math.PI/8; // radians
    var vel = 0; // cm/s
    var dx = 0.02; // s
    var acc, vel, penx, peny;
    
    //svg and d3.js
    var sphere;
    var string;
    var string2;
    var sphere2;
    
    //timing
    var start;
    
    var old_k = 1;
    var zoomFactor = .7;
    
    $( document ).ready(function() {
      start = (new Date()).getTime(); //start time on page load
    
      var svg = d3.select("body")
                .append("svg")
                .attr("width", '100%')
                .attr("height", '600px')
                .call(d3.zoom().on("zoom", function () {
                var delta = d3.event.transform.k - old_k
                d3.event.transform.k = old_k + zoomFactor*delta
                svg.attr("transform", d3.event.transform);
                old_k = d3.event.transform.k
            }))
            .append("g");
    
                var viewport = svg.append('g')
    
                var layer1 = viewport.append('g');
                var layer2 = viewport.append('g');
    
                sphere = layer2.append("circle")
                             .attr("cx", 30)
                             .attr("cy", 30)
                             .attr("r", 20)
                             .attr('fill', '#FF0000');
    
                string = layer1.append("rect")
                              .attr("x", 27)
                              .attr("y", 0)
                              .attr("width", 6)
                              .attr("height", 10);
    
                //The vertical pendulum
                sphere2 = layer2.append("circle")
                             .attr("cx", 609)
                             .attr("cy", 300)
                             .attr("r", 20)
                             .attr('fill', '#FF0000');
    
                string2 = layer1.append("line")
                            .attr("x1", 609.5)
                            .attr("y1", 0)
                            .attr("x2", 609.5)
                            .attr("y2", 310)
                            .attr("stroke-width", 4)
                            .attr("stroke", "black");
    
                var roof = layer1.append("rect")
                              .attr("x", -100000)
                              .attr("y", -60)
                              .attr("height", 55)
                              .attr("width", 200000)
                              .attr('fill', 'url(#diagonal-stripe-3)');
                              
                var border = layer1.append("rect")
                              .attr("x", -100000)
                              .attr("y", -10)
                              .attr("height", 10)
                              .attr("width", 200000)
                              .attr('fill', '#000000');
    
    
    
    
        controller = setInterval(controller, 30);  //start controller
    });
    
    function controller(){
    
      //horizontal pendulum
      sphere.attr('cy', Math.sin(start-(new Date()).getTime()/400-(Math.PI/4))*310+350);
      string.attr('height', Math.sin(start-(new Date()).getTime()/400-(Math.PI/4))*310+337);
      string.attr('width', Math.sin((start-(new Date()).getTime()/400-(Math.PI/4))-Math.PI)*3+6);
      string.attr('x', Math.sin((start-(new Date()).getTime()/400-(Math.PI/4)))*1.5-3+stepLR);
    
      //vertical pendulum
      acc = g * Math.cos(angle) * dx;
    				vel += acc * dx;
    				angle += vel * dx;
    				setPenPos();
    
    
      document.addEventListener("keydown", function (e) {
        if([e.keyCode] == 37){
          left();
        }
        if([e.keyCode] == 39){
          right();
        }
      });
    }
    
    function left(){
      stepLR=stepLR-speed;
      sphere.attr('cx', stepLR);
      string.attr('x', stepLR);
    }
    
    function right(){
      stepLR=stepLR+speed;
      sphere.attr('cx', stepLR);
      string.attr('x', stepLR);
    }
    
    function setPenPos(){
    				penx = cx + radius * Math.cos(angle);
    				peny = cy + radius * Math.sin(angle);
    				string2.attr("x2", penx);
    				string2.attr("y2", peny);
    				sphere2.attr("cx", penx);
    				sphere2.attr("cy", peny);
    			}
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://d3js.org/d3.v4.js"></script>
    
    <svg height="10" width="10" xmlns="http://www.w3.org/2000/svg" version="1.1"> <defs> <pattern id="diagonal-stripe-3" patternUnits="userSpaceOnUse" width="10" height="10"> <image xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+CiAgPHJlY3Qgd2lkdGg9JzEwJyBoZWlnaHQ9JzEwJyBmaWxsPSd3aGl0ZScvPgogIDxwYXRoIGQ9J00tMSwxIGwyLC0yCiAgICAgICAgICAgTTAsMTAgbDEwLC0xMAogICAgICAgICAgIE05LDExIGwyLC0yJyBzdHJva2U9J2JsYWNrJyBzdHJva2Utd2lkdGg9JzMnLz4KPC9zdmc+" x="0" y="0" width="10" height="10"> </image> </pattern> </defs> </svg>
    &#13;
    &#13;
    &#13;