2014-06-29 7 views
5

Ich hätte gerne vertikales Zoomen und horizontales Schwenken mit einem einfachen Balkendiagramm. Hier ist mein Beispiel: http://jsfiddle.net/bjames/rR7ee/.Waagerechte Waagschale mit Ordinal x Achse in d3

Das meiste, was ich versucht habe beinhaltet viewBox und ich verstehe, ich könnte mehr Glück mit einem clipPath haben. Aber alle Beispiele, die ich gefunden habe, verwenden eine kontinuierliche X-Achse in der Zoom-Funktion, um die Aufgabe zu erledigen.

In meinem Beispiel gibt es 8 Balken, aber nur 4 sind sichtbar. Ich möchte das Panel nach links ziehen. Was vermisse ich?

Vielen Dank im Voraus.

width = 600 
height = 600 
padding = {left:40, top:20, right:20, bottom:30} 
size = { 
    x: width - padding.left - padding.right, 
    y: height - padding.top - padding.bottom 
} 
var svg = d3.select('.container').append('div') 
    .append("svg") 
    .attr("width", 300) 
    .attr("height", height) 
    .attr('class', 'frame') 
    .append("g") 
    .attr("transform", "translate(" + padding.left + "," + 
      padding.top + ")") 


svg.append('rect') 
    .attr('class', 'background') 
    .attr('pointer-events', 'all') 
    .attr('fill', 'none') 
    .attr('height', size.y + 'px') 
    .attr('width', size.x + 'px') 


var d = [5,6,7,8,9,10,11,12] 

var x = d3.scale.ordinal() 
     .domain(d3.range(d.length)) 
     .rangeRoundBands([0, size.x], .15) 

var y = d3.scale.linear() 
      .domain([0,d3.max(d)]) 
      .range([size.y, 0]) 

var xax = d3.svg.axis().scale(x) 
      .tickSize(-size.y).orient('bottom') 

var yax = d3.svg.axis().scale(y) 
      .tickSize(-size.x).orient('left') 

svg.append("g") 
    .attr("class", "y axis") 
    .call(yax) 

svg.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + size.y+ ")") 
    .call(xax) 

svg.append('g').attr('class', 'rects') 

function update(){ 

    var rects = d3.select('.rects').selectAll('rect') 
        .data(d) 

    rects.attr('x', function(d,i) { return x(i)}) 
     .attr('width', x.rangeBand()) 
     .attr('y', function(d) { return y(d)}) 
     .attr('height', function(d) { return size.y - y(d)}) 

    rects.enter().append('rect') 
     .attr('x', function(d,i) { return x(i) }) 
     .attr('width', x.rangeBand()) 
     .attr('y', function(d) { return y(d)}) 
     .attr('height', function(d) { return size.y - y(d)}) 
     .style('fill', 'orange') 
    svg.select('.y.axis') 
     .call(yax) 
    svg.select('.x.axis') 
     .call(xax) 
    svg.select('.background') 
     .call(zoom) 
} 


var zoom = d3.behavior.zoom() 
      .on("zoom", zoomed) 

function zoomed() { 
    y.domain([0, d3.max(d)*1/d3.event.scale]) 
    update(); 
} 
update() 

Antwort

7

Das vertikale Zoomen wurde bereits implementiert. Ich habe das horizontale Schwenken implementiert.

Hinweis: Sowohl das Zoomen als auch das Schwenken erfolgen auf dem Rechteck im Hintergrund, wenn Hörer daran angehängt werden.

Ich habe Kommentare im Geigencode hinzugefügt, die Ihnen in der Logik helfen sollten.

width = 600 
height = 600 
padding = {left:40, top:20, right:20, bottom:30} 
size = { 
    x: width - padding.left - padding.right, 
    y: height - padding.top - padding.bottom 
} 
var svg = d3.select('.container').append('div') 
    .append("svg") 
    .attr("width", 300) 
    .attr("height", height) 
    .attr('class', 'frame') 
    .append("g") 
    .attr("transform", "translate(" + padding.left + "," + 
      padding.top + ")") 



svg.append('rect') 
    .attr('class', 'background') 
    .attr('pointer-events', 'all') 
    .attr('fill', 'none') 
    .attr('height', size.y + 'px') 
    .attr('width', size.x + 'px') 


var d = [5,6,7,8,9,10,11,12] 

var x = d3.scale.ordinal() 
     .domain(d3.range(d.length)) 
     .rangeRoundBands([0, size.x], .15) 

var y = d3.scale.linear() 
      .domain([0,d3.max(d)]) 
      .range([size.y, 0]) 

var xax = d3.svg.axis().scale(x) 
      .tickSize(-size.y).orient('bottom') 

var yax = d3.svg.axis().scale(y) 
      .tickSize(-size.x).orient('left') 

svg.append("g") 
    .attr("class", "y axis") 
    .call(yax) 

svg.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + size.y+ ")") 
    .call(xax) 
var svg1 = svg.append('svg') 
    .attr('height', size.y + 'px') 
    .attr('width', size.x + 'px') 
svg1.append('g').attr('class', 'rects') 

function update(){ 

    var rects = d3.select('.rects').selectAll('rect') 
        .data(d) 

    rects.attr('x', function(d,i) { return x(i)}) 
     .attr('width', x.rangeBand()) 
     .attr('y', function(d) { return y(d)}) 
     .attr('height', function(d) { return size.y - y(d)}) 

    rects.enter().append('rect') 
     .attr('x', function(d,i) { return x(i) }) 
     .attr('width', x.rangeBand()) 
     .attr('y', function(d) { return y(d)}) 
     .attr('height', function(d) { return size.y - y(d)}) 
     .style('fill', 'orange') 
    svg.select('.y.axis') 
     .call(yax) 
    svg.select('.x.axis') 
     .call(xax) 
    svg.select('.background') 
     .call(zoom) 
    svg.select('.background') 
     .call(drag) 
} 


var zoom = d3.behavior.zoom() 
      .on("zoom", zoomed) 

function zoomed() { 
    y.domain([0, d3.max(d)*1/d3.event.scale]) 
    update(); 
} 
var drag = d3.behavior.drag() 
    .on("drag", dragmove).on("dragstart", dragstart); 

var moved = 0;//record the translate x moved by the g which contains the bars. 
var dragStartX = 0;//record teh point from where the drag started 
var oldTranslateX = 0; 

function dragstart(d){ 
    dragStartX = d3.event.sourceEvent.clientX; 
    oldTranslateX = moved;//record the old translate 
    console.log(d3.event) 
} 
function dragmove(d) { 
    var x = d3.event.x; 
    var y = d3.event.y; 
    var dx = x-dragStartX 
    x = dx + oldTranslateX + 50; //add teh old translate to the dx to get the resultant translate 
    moved = x; //record the translate x given 
    //move the bars via translate x 
    d3.select('.rects').attr("transform", "translate(" + x + "," + 0 + ")"); 
    //move the x axis via translate x 
    d3.select('.x').attr("transform", "translate("+x +" ," + size.y+ ")") 
} 
update() 

Hier ist die Geige: http://jsfiddle.net/cyril123/o0qeom7n/3/

+0

Dynamit. Diese Frage ist so alt und ich habe keine Zeit, sie jetzt zu lesen, aber es funktioniert eindeutig, also nenne ich sie den Gewinner. Ich freue mich darauf, es mir anzusehen. –

+0

Es sieht so aus, als ob die X-Achsenbeschriftungen beim Panning nicht richtig ausgeblendet werden. Die Beschriftungen erstrecken sich nur über die Kante des Graphen hinaus. Weißt du, wie das zu beheben ist? –

+1

Das Zoom- und Ziehverhalten ist nur im Hintergrund verfügbar, nicht wenn sich der Mauszeiger über den Rechtecken befindet. Vielleicht möchtest du etwas hinzufügen wie 'svg1.attr ('pointer-events', 'none')', um die gesamte svg zoomen und ziehen zu können. Siehe [Update] (http://jsfiddle.net/o0qeom7n/4/). – altocumulus