Zbudowałem wykres rozproszenia d3.js z funkcją powiększania/przesuwania. Możesz zobaczyć pełną treść (kliknij "Otwórz w nowym oknie", aby zobaczyć całość): http://bl.ocks.org/129f64bfa2b0d48d27c9Wykres rozproszenia d3.js - granice powiększania/przeciągania, przyciski powiększania, resetowanie powiększenia, obliczanie mediany
Jest kilka funkcji, których nie mogłem zrozumieć, które chciałbym ręka z nim, jeśli ktoś może wskazać mi w dobrym kierunku:
- Chcę zastosować granice X/Y zoom/pan w tym obszarze, aby nie można było przeciągnąć go poniżej określonego punktu (np.).
- Udało mi się też nakręcić przyciski stylu +/- Zoom w Mapach Google bez żadnych sukcesów. Jakieś pomysły?
Znacznie mniej ważniejsze, istnieje również kilka obszarów, w których mam zorientowali się rozwiązanie, ale jest to bardzo szorstki, więc jeśli masz lepsze rozwiązanie to proszę daj mi znać:
- Dodałem przycisk "resetowania zoomu", ale po prostu usuwa on wykres i zamiast niego generuje nowy obiekt zamiast powiększać obiekty. Idealnie powinien zresetować zoom.
Napisałem własną funkcję obliczania mediany danych X i Y. Jednak jestem pewien, że musi istnieć lepszy sposób na zrobienie tego przy pomocy d3.median, ale nie wiem, jak to zrobić.
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; };
bardzo uproszczona (np życia) wersja JS jest poniżej. Można znaleźć pełną skrypt na 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)+")";
});
};
}
});
Wszelkie pomoc byłaby znacznie doceniane. Dzięki!
Edycja: Oto podsumowanie poprawek użyłem, na podstawie sugestii Superboggly jest poniżej:
// 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]]);
}
...
};
Tłumaczenie zoom że użyłem jest bardzo doraźne i zasadniczo wykorzystuje abitrary stałe zachować ustawienie lub więcej mniej w odpowiednim miejscu. To nie jest idealne i chętnie bym zaproponował bardziej uniwersalną technikę dźwiękową. Jednak w tym przypadku działa wystarczająco dobrze.
Jeszcze raz dziękuję Superboggly! Twój kod zoomIn/reset wydaje się działać, ale skala zmienia się tylko w następnym zdarzeniu zoomu (tj. Po przeciągnięciu lub obróceniu koła myszy). Mam problem z aktualizacją rzeczy po kliknięciu przycisku. To musi być proste, ale po prostu nie mogę tego rozgryźć. Mój kod kliknięcia przycisku to: d3.select ("# zoomIn"). Call (zoom) .on ("kliknij", funkcja() { d3.event.preventDefault(); zm.scale (zm.scale () * 2); }); Próbowałem różnych zastosowań funkcji .call(), zoom() i .on() bezskutecznie. – richardwestenra
Dodałem szybki mały niebieski kwadrat powiększenia u dołu mojego [ostatniego jsfiddle dla ciebie] (http://jsfiddle.net/superboggly/SD5cK/2/). Brakuje tylko połączenia z zoomem() po ustawieniu skali. Pomyśl o funkcji zoomu, którą dostarczyłeś jako stosującej stan powiększenia obliczony przez zachowanie. – Superboggly
w porządku! Sortowane! Okazuje się, że to jest dokładnie to, co robiłem, ale to nie działało dla mnie ... Krótko mówiąc: Używałeś d3 wersji 3, gdy używałem wersji 2, i dlatego to nie działało, kiedy upuściłem niebieski kwadrat w moim kodzie. Zaktualizowałem do wersji 3 i teraz działa. Pozdrawiam :) – richardwestenra