2016-02-05 8 views
14

私はズームとパンはx軸のために働いていますが、私はy軸用のパンを追加したいと思います。私は、y翻訳値を取得して、それを使用しますが、クリックドラッグは、y軸をパンしながら、また、ズームする(非直感的な方法で)y軸をパンして起こるズーム時に値の変更を翻訳しd3.behavior.zoomd3.event.translate[1]を使用してみました。D3:1つの軸をズーム+パンし、もう一方のパンだけをパンすることはできますか?

x軸用とy軸用の2つのd3.behavior.zoomインスタンスも使用しましたが、追加された最後のものだけがズームイベントで呼び出されます。ここで

は、私があまりにも(ただし、Yズーミング)パンのyを追加したいというのx方向のズームとパンのために動作例を示します。この中

var x = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var y = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var rectangleSelector = d3.select('svg') 
 
    .append('g') 
 
    .selectAll('rect') 
 
    .data([[0, 0], [50, 50], [100, 100]]) 
 
    .enter() 
 
    .append('rect') 
 
    .attr('fill', 'black') 
 
    .attr('x', d => x(d[0])) 
 
    .attr('y', d => y(d[1])) 
 
    .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
    .attr('height', d => y(40)); 
 
    
 
d3.select('svg') 
 
    .call(d3.behavior.zoom().x(x).on('zoom',() => { 
 
    rectangleSelector 
 
     .attr('x', d => x(d[0])) 
 
     .attr('y', d => y(d[1])) 
 
     .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
     .attr('height', d => y(40)); 
 
    }));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<svg width="800" height="800"></svg>

たとえば私はd3.event.translate[1]からyの値を使用しようとすると、それはドラッグのために動作しますが、望ましくない動作は、ユーザーのマウスもズームされている場所に依存してy軸に対して平行移動値を変更することです。

var x = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var y = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var rectangleSelector = d3.select('svg') 
 
    .append('g') 
 
    .selectAll('rect') 
 
    .data([[0, 0], [50, 50], [100, 100]]) 
 
    .enter() 
 
    .append('rect') 
 
    .attr('fill', 'black') 
 
    .attr('x', d => x(d[0])) 
 
    .attr('y', d => y(d[1])) 
 
    .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
    .attr('height', d => y(40)); 
 
    
 
d3.select('svg') 
 
    .call(d3.behavior.zoom().x(x).on('zoom',() => { 
 
    var translateY = d3.event.translate[1]; 
 
    
 
    rectangleSelector 
 
     .attr('x', d => x(d[0])) 
 
     .attr('y', d => y(d[1] + translateY)) 
 
     .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
     .attr('height', d => y(40)); 
 
    }));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<svg width="800" height="800"></svg>

+0

'd3.behavior.zoom()' ')(' X() ''とYとの連鎖可能です。私は 'x()'のみを指定しているので、ズームの振る舞いはx軸だけを変更します。しかし、私はその軸を変換するために使用したいy軸の値の変換を報告しています。パンニングだけでなくズーミングの影響を受けるという問題があります。 – Beau

+1

私はJSFiddleも作成中です。 – Beau

+0

多分これは:http://bl.ocks.org/jgbos/9752277 – altocumulus

答えて

10

JSFIDDLE:手始めにhttps://jsfiddle.net/sladav/o8vaecyn/

、ズーム動作は、x軸のパンとズームの両方を処理し、それはによって処理されます...

var zoom = d3.behavior.zoom() 
    .x(x) 
    .scaleExtent([1, 10]) 
    .on("zoom", zoomed); 

だから我々はにズームを使用しますx軸のものを扱う。 Y軸の

JUSTパン動作を取得するには...

は、「DY」を取り込み、Yドメインを移行し、それを再適用する別のドラッグ動作を作成します。

  1. var yPan = 0; 
    var yMin = (-height/2); 
    var yMax = (height/2); 
    
    var y = d3.scale.linear() 
        .domain([yMin, yMax]) 
        .range([height, 0]); 
    
  2. (我々はドラッグすると、それを修正します)再スケーリングする機能を追加Yスケールのドメインを変数とするドラッグ動作

    var drag = d3.behavior.drag() 
        .on("drag", dragging) 
    
  3. に追加ドラッグイベントのY軸

    function dragging(d) { 
        yPan = d3.event.dy; 
        yMin += yPan; 
        yMax += yPan; 
        y.domain([yMin, yMax]) 
        d3.select(".y.axis").call(yAxis)}; 
    
  4. あなたのSVG要素からドラッグ関数を呼び出し

    var svg = d3.select("body").append("svg") 
        .attr("width", width + margin.left + margin.right) 
        .attr("height", height + margin.top + margin.bottom) 
        .append("g") 
         .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
         .call(zoom) 
         .call(drag); 
    
2

私はこれを行うための一つの方法を考え出したが、それは巨大なハックのように感じている:

var lastY = 0; 

var zoom = d3.behavior.zoom().x(x); 

zoom.on('zoom',() => { 
    var translateY; 

    if (d3.event.sourceEvent.type === 'mousemove') { 
    // if it's a drag event then use the value from the drag 
    translateY = d3.event.translate[1]; 
    lastY = translateY; 
    } else { 
    // if it's a wheel event then set the y translation to the last value 
    translateY = lastY; 
    zoom.translate([d3.event.translate[0], translateY]); 
    } 

    // translateY can now be used here as an offset to any drawing like so: 
    rectangleSelector.attr('y', y(d[1] + translateY)); 
}); 
0

あなたは、コードビットクリーナーを取得するために

zoom.center
を使用することができ、このような:

var lastY = 0; 
 
var x = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var y = d3.scale.linear() 
 
    .domain([0, 800]) 
 
    .range([0, 800]); 
 

 
var rectangleSelector = d3.select('svg') 
 
    .append('g') 
 
    .selectAll('rect') 
 
    .data([[0, 0], [50, 50], [100, 100]]) 
 
    .enter() 
 
    .append('rect') 
 
    .attr('fill', 'black') 
 
    .attr('x', d => x(d[0])) 
 
    .attr('y', d => y(d[1])) 
 
    .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
    .attr('height', d => y(40)); 
 
    
 
var zoom = d3.behavior.zoom().center([400, 400]).x(x); 
 
zoom.on('zoom',() => { 
 
    var translateY = d3.event.translate[1]; 
 
    zoom.center([400, translateY]); 
 
    rectangleSelector.attr('x', d => x(d[0])) 
 
         .attr('y', d => y(d[1] + translateY)) 
 
         .attr('width', d => x(d[0] + 40) - x(d[0])) 
 
         .attr('height', d => y(40)); 
 
}); 
 

 
d3.select('svg').call(zoom);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<svg width="800" height="800"></svg>

+0

このスニペットを試してみると、最初のズームが縦軸を変更することがあります – Beau

+0

最初の中心をどのように設定するかによって異なります。 Y軸の最初のズームを50に変更することもできます(この場合、最初のY軸の中央になります) – Doktorn

関連する問題