Ich habe ein d3.js Streudiagramm mit Zoom/Schwenk-Funktionalität erstellt. Sie können die ganze Sache hier sehen (klicken Sie auf "In einem neuen Fenster öffnen", um die ganze Sache zu sehen): http://bl.ocks.org/129f64bfa2b0d48d27c9d3.js Streudiagramm - zoomen/ziehen Grenzen, Zoom-Tasten, Zoom zurücksetzen, Median berechnen
Es gibt ein paar Funktionen, die ich nicht herausfinden konnte, dass ich würde lieben eine Hand mit ihm, wenn jemand mich in der richtigen Richtung zeigen kann:
- ich mag X/Y Zoom/pan-Grenzen auf den Bereich anzuwenden, so dass Sie es nicht unter einem bestimmten Punkt ziehen (zB Null).
- Ich habe auch einen Stich bei der Erstellung von Google Maps Stil +/- Zoom-Tasten gemacht, ohne Erfolg. Irgendwelche Ideen?
Viel weniger wichtig ist, gibt es auch ein paar Bereiche, in denen ich eine Lösung herausgefunden haben, aber es ist sehr rau, so dass, wenn Sie eine bessere Lösung haben, dann gehen Sie bitte lassen Sie mich wissen:
- Ich habe eine "Reset Zoom" -Taste hinzugefügt, aber es löscht nur die Grafik und erzeugt eine neue an ihrer Stelle, anstatt tatsächlich die Objekte zu zoomen. Idealerweise sollte der Zoom zurückgesetzt werden.
Ich habe meine eigene Funktion geschrieben, um den Median der X- und Y-Daten zu berechnen. Ich bin mir jedoch sicher, dass es einen besseren Weg geben muss, dies mit d3.median zu tun, aber ich kann nicht herausfinden, wie es funktioniert.
var xMed = median(_.map(data,function(d){ return d.TotalEmployed2011;})); var yMed = median(_.map(data,function(d){ return d.MedianSalary2011;})); function median(values) { values.sort(function(a,b) {return a - b;}); var half = Math.floor(values.length/2); if(values.length % 2) return values[half]; else return (parseFloat(values[half-1]) + parseFloat(values[half]))/2.0; };
Eine sehr vereinfacht (das heißt alte) Version des JS ist unten. Sie können die vollständige Skript finden bei https://gist.github.com/richardwestenra/129f64bfa2b0d48d27c9#file-main-js
d3.csv("js/AllOccupations.csv", function(data) {
var margin = {top: 30, right: 10, bottom: 50, left: 60},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xMax = d3.max(data, function(d) { return +d.TotalEmployed2011; }),
xMin = 0,
yMax = d3.max(data, function(d) { return +d.MedianSalary2011; }),
yMin = 0;
//Define scales
var x = d3.scale.linear()
.domain([xMin, xMax])
.range([0, width]);
var y = d3.scale.linear()
.domain([yMin, yMax])
.range([height, 0]);
var colourScale = function(val){
var colours = ['#9d3d38','#c5653a','#f9b743','#9bd6d7'];
if (val > 30) {
return colours[0];
} else if (val > 10) {
return colours[1];
} else if (val > 0) {
return colours[2];
} else {
return colours[3];
}
};
//Define X axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(-height)
.tickFormat(d3.format("s"));
//Define Y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width)
.tickFormat(d3.format("s"));
var svg = d3.select("#chart").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(d3.behavior.zoom().x(x).y(y).scaleExtent([1, 8]).on("zoom", zoom));
svg.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Create points
svg.selectAll("polygon")
.data(data)
.enter()
.append("polygon")
.attr("transform", function(d, i) {
return "translate("+x(d.TotalEmployed2011)+","+y(d.MedianSalary2011)+")";
})
.attr('points','4.569,2.637 0,5.276 -4.569,2.637 -4.569,-2.637 0,-5.276 4.569,-2.637')
.attr("opacity","0.8")
.attr("fill",function(d) {
return colourScale(d.ProjectedGrowth2020);
});
// Create X Axis label
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height + margin.bottom - 10)
.text("Total Employment in 2011");
// Create Y Axis label
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", -margin.left)
.attr("x", 0)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text("Median Annual Salary in 2011 ($)");
function zoom() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll("polygon")
.attr("transform", function(d) {
return "translate("+x(d.TotalEmployed2011)+","+y(d.MedianSalary2011)+")";
});
};
}
});
Jede Hilfe massiv geschätzt würde. Vielen Dank!
Edit: Hier ist eine Zusammenfassung der Fixes I, bezogen auf Superboggly Vorschläge unter:
// Zoom in/out buttons:
d3.select('#zoomIn').on('click',function(){
d3.event.preventDefault();
if (zm.scale()< maxScale) {
zm.translate([trans(0,-10),trans(1,-350)]);
zm.scale(zm.scale()*2);
zoom();
}
});
d3.select('#zoomOut').on('click',function(){
d3.event.preventDefault();
if (zm.scale()> minScale) {
zm.scale(zm.scale()*0.5);
zm.translate([trans(0,10),trans(1,350)]);
zoom();
}
});
// Reset zoom button:
d3.select('#zoomReset').on('click',function(){
d3.event.preventDefault();
zm.scale(1);
zm.translate([0,0]);
zoom();
});
function zoom() {
// To restrict translation to 0 value
if(y.domain()[0] < 0 && x.domain()[0] < 0) {
zm.translate([0, height * (1 - zm.scale())]);
} else if(y.domain()[0] < 0) {
zm.translate([d3.event.translate[0], height * (1 - zm.scale())]);
} else if(x.domain()[0] < 0) {
zm.translate([0, d3.event.translate[1]]);
}
...
};
Die Zoom-Übersetzung, die ich verwendet wird, sehr ad hoc und verwendet grundsätzlich abitrary Konstanten, die Stellung zu halten, mehr oder weniger am richtigen Ort. Es ist nicht ideal, und ich wäre bereit, Vorschläge für eine universellere Technik zu unterbreiten. In diesem Fall funktioniert es jedoch gut genug.
Danke nochmal Superboggly! Ihr ZoomIn/Reset-Code scheint zu funktionieren, aber der Maßstab ändert sich nur beim nächsten Zoom-Ereignis (d. H. Beim Ziehen oder Mausrad). Es fällt mir schwer, die Dinge per Knopfdruck zu aktualisieren. Es muss einfach sein, aber ich kann es einfach nicht herausfinden. Mein Tastenklick-Code ist: d3.select ('# zoomIn'). Aufruf (Zoom) .on ('click', function() { d3.event.preventDefault(); zm.scale (zm.scale () * 2); }); Ich habe verschiedene Verwendungen von .call(), zoom() und .on() vergeblich versucht. – richardwestenra
Ich habe ein kleines blaues Zoom-Quadrat am unteren Rand meines [letzten Jfiddle für Sie] hinzugefügt (http://jsfiddle.net/superboggly/SD5cK/2/). Alles, was Sie verpassen, ist ein Aufruf zum Zoomen(), nachdem Sie die Skalierung festgelegt haben. Stellen Sie sich die Zoom-Funktion vor, die Sie angegeben haben, indem Sie den vom Verhalten berechneten Zoom-Zustand anwenden. – Superboggly
okay! Sortiert! Es stellt sich heraus, dass es genau das ist, was ich gemacht habe, aber es funktionierte nicht für mich ... Lange Rede, kurzer Sinn: Du hast d3 Version 3 benutzt, während ich Version 2 benutzt habe, und deshalb hat es nicht funktioniert, als ich deine fallen gelassen habe blaues Quadrat in meinem Code. Habe auf v3 aktualisiert und es funktioniert jetzt. Prost :) – richardwestenra