2016-02-05 84 views
14

我有縮放和平移工作的X軸,但我想補充平移Y軸。我嘗試使用d3.behavior.zoomd3.event.translate[1]來獲得y翻譯值並使用該值,但當縮放發生時翻譯值發生變化,因此點擊拖動確實會平移y軸,縮放也會以非直觀方式平移y軸。D3:是否可以縮放+平移一個軸,只平移另一個軸?

我也嘗試使用兩個d3.behavior.zoom實例,一個用於x軸,另一個用於y軸,但只有最後一個添加的縮放事件被調用。

下面是在x方向縮放和平移,我還想加上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',() => { 
 
    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()'和'ÿ環連接()';我只指定'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 drag = d3.behavior.drag() 
        .on("drag", dragging) 
    
  2. 讓Y比例的域變量(我們將修改,當我們拖動)

    var yPan = 0; 
    var yMin = (-height/2); 
    var yMax = (height/2); 
    
    var y = d3.scale.linear() 
        .domain([yMin, yMax]) 
        .range([height, 0]); 
    
  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

相關問題