2016-12-30 2 views
0

Ich versuche, eine D3.JS scrollbare Liniendiagramm zum automatischen Nachjustieren der Achsen basierend auf der aktuellen Ansicht des Benutzers zu erhalten.Aktualisieren Sie Achsen auf D3.JS scrollbaren Liniendiagramm basierend auf der Ansicht des Benutzers

Um ein Beispiel zu geben, kann das beabsichtigte Verhalten auf Google Finanzen gesehen werden.

Im ersten Diagramm können Sie den Preis sehen bei rund 5485 Peaking:

enter image description here

Im zweiten Diagramm, ich habe gescrollt nach vorne und Sie können, dass das Diagramm neu skaliert automatisch sehen Urlaub mit der neuen Spitze bei 5510:

enter image description here

Beachten Sie, dass dieses Verhalten anspricht, die sich leicht, indem man das en erreicht werden kann, um einfach machen das Diagramm unterscheidet Reifen Diagramm, einschließlich den Daten außerhalb der Sicht des Benutzers, in einem ansprechenden Behälter, zB:

.svg-container { 
    display: inline-block; 
    position: relative; 
    width: 100%; 
    padding-bottom: 65%; 
    vertical-align: top; 
    overflow: hidden; 
} 

Um dieses Problem zu lösen, müsste ich zur Zeit zwischen der Gesamtheit der Preisentwicklung und dem Segment der Benutzer unterscheiden sind Betrachten und dann den y-Achsenbereich einstellen. Wie kann ich das erreichen?

Antwort

1

Nicht sicher, dass ich die Frage verstehe, aber es scheint, als ob Sie nur die Y-Achse skalieren möchten, wenn sich der ausgewählte Datenbereich ändert. Ich baue this classic example ab, ich habe es so geändert, dass beim Putzen oder Zoomen die Y-Achsen-Domäne geändert wird, damit sie der aktuellen Auswahl entspricht. Der Schlüsselcode ist dies in dem brushed Rückruf:

// set new y domain based on selection 
y.domain([0, d3.max(data, function(d) { 
    if (d.x < x.domain()[0] || d.x > x.domain()[1]) return 0; 
    else return d.y; 
})]); 
// redraw y axis 
focus.select(".axis--y").call(yAxis); 

Komplettes Beispiel:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    .area { 
 
    fill: steelblue; 
 
    clip-path: url(#clip); 
 
    } 
 
    
 
    .zoom { 
 
    cursor: move; 
 
    fill: none; 
 
    pointer-events: all; 
 
    } 
 
</style> 
 
<svg width="960" height="500"></svg> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<script> 
 
    var svg = d3.select("svg"), 
 
    margin = { 
 
     top: 20, 
 
     right: 20, 
 
     bottom: 110, 
 
     left: 40 
 
    }, 
 
    margin2 = { 
 
     top: 430, 
 
     right: 20, 
 
     bottom: 30, 
 
     left: 40 
 
    }, 
 
    width = +svg.attr("width") - margin.left - margin.right, 
 
    height = +svg.attr("height") - margin.top - margin.bottom, 
 
    height2 = +svg.attr("height") - margin2.top - margin2.bottom; 
 

 
    var x = d3.scaleLinear().range([0, width]), 
 
    x2 = d3.scaleLinear().range([0, width]), 
 
    y = d3.scaleLinear().range([height, 0]), 
 
    y2 = d3.scaleLinear().range([height2, 0]); 
 

 
    var xAxis = d3.axisBottom(x), 
 
    xAxis2 = d3.axisBottom(x2), 
 
    yAxis = d3.axisLeft(y); 
 

 
    var brush = d3.brushX() 
 
    .extent([ 
 
     [0, 0], 
 
     [width, height2] 
 
    ]) 
 
    .on("brush end", brushed); 
 

 
    var zoom = d3.zoom() 
 
    .scaleExtent([1, Infinity]) 
 
    .translateExtent([ 
 
     [0, 0], 
 
     [width, height] 
 
    ]) 
 
    .extent([ 
 
     [0, 0], 
 
     [width, height] 
 
    ]) 
 
    .on("zoom", zoomed); 
 

 
    var area = d3.area() 
 
    .curve(d3.curveMonotoneX) 
 
    .x(function(d) { 
 
     return x(d.x); 
 
    }) 
 
    .y0(height) 
 
    .y1(function(d) { 
 
     return y(d.y); 
 
    }); 
 

 
    var area2 = d3.area() 
 
    .curve(d3.curveMonotoneX) 
 
    .x(function(d) { 
 
     return x2(d.x); 
 
    }) 
 
    .y0(height2) 
 
    .y1(function(d) { 
 
     return y2(d.y); 
 
    }); 
 

 
    svg.append("defs").append("clipPath") 
 
    .attr("id", "clip") 
 
    .append("rect") 
 
    .attr("width", width) 
 
    .attr("height", height); 
 

 
    var focus = svg.append("g") 
 
    .attr("class", "focus") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    var context = svg.append("g") 
 
    .attr("class", "context") 
 
    .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); 
 

 
    var data = []; 
 
    for (var i = 0; i < 100; i++) { 
 
    data.push({ 
 
     x: i, 
 
     y: i > 50 ? Math.random() * 100 : Math.random() * 50 
 
    }); 
 
    } 
 

 
    x.domain(d3.extent(data, function(d) { 
 
    return d.x; 
 
    })); 
 
    y.domain([0, d3.max(data, function(d) { 
 
    return d.y; 
 
    })]); 
 
    x2.domain(x.domain()); 
 
    y2.domain(y.domain()); 
 

 
    focus.append("path") 
 
    .datum(data) 
 
    .attr("class", "area") 
 
    .attr("d", area); 
 

 
    focus.append("g") 
 
    .attr("class", "axis axis--x") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
    focus.append("g") 
 
    .attr("class", "axis axis--y") 
 
    .call(yAxis); 
 

 
    context.append("path") 
 
    .datum(data) 
 
    .attr("class", "area") 
 
    .attr("d", area2); 
 

 
    context.append("g") 
 
    .attr("class", "axis axis--x") 
 
    .attr("transform", "translate(0," + height2 + ")") 
 
    .call(xAxis2); 
 

 
    context.append("g") 
 
    .attr("class", "brush") 
 
    .call(brush) 
 
    .call(brush.move, x.range()); 
 

 
    svg.append("rect") 
 
    .attr("class", "zoom") 
 
    .attr("width", width) 
 
    .attr("height", height) 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
 
    .call(zoom); 
 

 
    function brushed() { 
 
    if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom 
 
    var s = d3.event.selection || x2.range(); 
 
    x.domain(s.map(x2.invert, x2)); 
 
    focus.select(".area").attr("d", area); 
 
    focus.select(".axis--x").call(xAxis); 
 

 
    y.domain([0, d3.max(data, function(d) { 
 
     if (d.x < x.domain()[0] || d.x > x.domain()[1]) return 0; 
 
     else return d.y; 
 
    })]); 
 
    focus.select(".axis--y").call(yAxis); 
 

 
    svg.select(".zoom").call(zoom.transform, d3.zoomIdentity 
 
     .scale(width/(s[1] - s[0])) 
 
     .translate(-s[0], 0)); 
 
    } 
 

 
    function zoomed() { 
 
    if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush 
 
    var t = d3.event.transform; 
 
    x.domain(t.rescaleX(x2).domain()); 
 
    focus.select(".area").attr("d", area); 
 
    focus.select(".axis--x").call(xAxis); 
 

 
    y.domain([0, d3.max(data, function(d) { 
 
     if (d.x < x.domain()[0] || d.x > x.domain()[1]) return 0; 
 
     else return d.y; 
 
    })]); 
 
    focus.select(".axis--y").call(yAxis); 
 

 
    context.select(".brush").call(brush.move, x.range().map(t.invertX, t)); 
 
    } 
 
</script>

+0

Ja, das, was ich mich zu tun versuchen. Ich habe später mit dem gleichen Beispiel in Ihrem Link gearbeitet, konnte aber nicht erreichen, dass die Y-Achse beim Pinsel korrekt gezeichnet wird. Vielen Dank. – Martin

Verwandte Themen