Załóżmy, że mam skrypt histogramu, który buduje grafikę 960 500 svg. Jak sprawić, by to reagowało, więc zmieniając szerokość, szerokość i wysokość grafiki były dynamiczne?
<script>
var n = 10000, // number of trials
m = 10, // number of random variables
data = [];
// Generate an Irwin-Hall distribution.
for (var i = 0; i < n; i++) {
for (var s = 0, j = 0; j < m; j++) {
s += Math.random();
}
data.push(s);
}
var histogram = d3.layout.histogram()
(data);
var width = 960,
height = 500;
var x = d3.scale.ordinal()
.domain(histogram.map(function(d) { return d.x; }))
.rangeRoundBands([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(histogram.map(function(d) { return d.y; }))])
.range([0, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("rect")
.data(histogram)
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return height - y(d.y); })
.attr("height", function(d) { return y(d.y); });
svg.append("line")
.attr("x1", 0)
.attr("x2", width)
.attr("y1", height)
.attr("y2", height);
</script>
Pełny przykładowy wykres histogramu to: https://gist.github.com/993912
javascript
responsive-design
d3.js
Matt Alcock
źródło
źródło
Odpowiedzi:
Jest inny sposób na to, który nie wymaga przerysowywania wykresu i polega na modyfikacji atrybutów viewBox i preserveAspectRatio na
<svg>
elemencie:Aktualizacja 24.11.2015 : większość współczesnych przeglądarek może wywnioskować proporcje elementów SVG na podstawie
viewBox
, więc może nie być konieczne aktualizowanie rozmiaru wykresu. Jeśli potrzebujesz obsługi starszych przeglądarek, możesz zmienić rozmiar swojego elementu, gdy rozmiar okna się zmieni:Zawartość SVG zostanie automatycznie przeskalowana. Możesz zobaczyć działający przykład tego (z pewnymi modyfikacjami) tutaj : wystarczy zmienić rozmiar okna lub prawy dolny panel, aby zobaczyć, jak zareaguje.
źródło
onload
wywołania funkcji. Jeśli szerokość i wysokość svg są ustawione w rzeczywistym html i użyjesz powyższej techniki, obraz nie będzie skalowalny.Poszukaj „responsive SVG”. Bardzo łatwo jest stworzyć responsive SVG i nie musisz się już martwić o rozmiary.
Oto jak to zrobiłem:
Kod CSS:
Więcej informacji / tutoriale:
http://demosthenes.info/blog/744/Make-SVG-Responsive
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
źródło
Napisałem małą istotę, aby rozwiązać ten problem.
Ogólny wzorzec rozwiązania jest następujący:
Dodałem również zminimalizowany skrypt d3.js dla prędkości. Istota jest tutaj: https://gist.github.com/2414111
kod zwrotny referencji jquery:
Kod odrzucenia:
Cieszyć się!
źródło
Bez użycia ViewBox
Oto przykład rozwiązania, które nie polega na użyciu
viewBox
:Klucz jest w aktualizowanie zakres z łusek , które są wykorzystywane do umieszczania danych.
Najpierw obliczyć oryginalny współczynnik kształtu:
Następnie na każdej rozmiaru, zaktualizuj
range
odx
iy
:Należy pamiętać, że wysokość zależy od szerokości i współczynnika kształtu, dzięki czemu zachowane zostaną oryginalne proporcje.
Na koniec „przerysuj” wykres - zaktualizuj dowolny atrybut, który zależy od jednej z
x
luby
skal:Należy zauważyć, że w re-doborze
rects
można użyć górny związany zrange
oy
, zamiast jawnie przy użyciu wysokość:Pokaż fragment kodu
źródło
Jeśli używasz d3.js do c3.js, rozwiązanie problemu z odpowiedzią jest dość proste:
gdzie wygląda wygenerowany kod HTML:
źródło
Odpowiedź Shawna Allena była świetna. Ale możesz nie chcieć tego robić za każdym razem. Jeśli hostujesz go na vida.io , automatycznie reagujesz na wizualizację SVG .
Za pomocą tego prostego kodu do umieszczenia można uzyskać responsywny element iframe:
http://jsfiddle.net/dnprock/npxp3v9d/1/
Ujawnienie: buduję tę funkcję w vida.io .
źródło
W przypadku korzystania z opakowania d3, takiego jak plottable.js , należy pamiętać, że najłatwiejszym rozwiązaniem może być dodanie detektora zdarzeń, a następnie wywołanie funkcji przerysowania (
redraw
w plottable.js). W przypadku plottable.js zadziała to doskonale (takie podejście jest słabo udokumentowane):źródło
W przypadku, gdy ludzie nadal odwiedzają to pytanie - oto, co zadziałało dla mnie:
Zawiąż ramkę iframe w div i użyj css, aby dodać dopełnienie, powiedzmy, 40% do tego div (procent w zależności od pożądanego współczynnika proporcji). Następnie ustaw zarówno szerokość, jak i wysokość samego elementu iframe na 100%.
W dokumencie HTML zawierającym wykres, który ma zostać załadowany do ramki iframe, ustaw szerokość na szerokość div, do której dołączany jest plik svg (lub na szerokość ciała) i ustaw proporcje wysokości do szerokości *.
Napisz funkcję, która ponownie ładuje zawartość iframe po zmianie rozmiaru okna, aby dostosować rozmiar wykresu, gdy ludzie obracają telefon.
Przykład tutaj na mojej stronie: http://dirkmjk.nl/en/2016/05/embedding-d3js-charts-responsive-website
AKTUALIZACJA 30 grudnia 2016 r
Podejście, które opisałem powyżej, ma pewne wady, zwłaszcza że nie bierze pod uwagę wysokości żadnego tytułu i podpisów, które nie są częścią svg utworzonego w D3. Od tamtej pory natknąłem się na lepsze podejście:
Przykład tutaj na mojej stronie internetowej: http://dirkmjk.nl/en/2016/12/embedding-d3js-charts-responsive-website-better-solution
źródło
Jedną z podstawowych zasad łączenia danych D3 jest to, że jest idempotentny. Innymi słowy, jeśli wielokrotnie oceniasz połączenie danych z tymi samymi danymi, renderowany wynik jest taki sam. Dlatego tak długo, jak poprawnie wyrenderujesz wykres, zachowując ostrożność przy wprowadzaniu, aktualizacji i wychodzeniu - wszystko, co musisz zrobić, gdy zmienia się rozmiar, to ponownie renderuj wykres w całości.
Jest kilka innych rzeczy, które powinieneś zrobić, jedną z nich jest odskakiwanie modułu zmiany rozmiaru okna w celu dławienia go. Ponadto zamiast sztywnych szerokości / wysokości należy to osiągnąć poprzez pomiar elementu zawierającego.
Alternatywnie, oto twój wykres renderowany przy użyciu d3fc , który jest zestawem składników D3, które poprawnie obsługują łączenia danych. Ma także kartezjańską tabelę, która mierzy ją, zawierając element, co ułatwia tworzenie „responsywnych” wykresów:
Możesz zobaczyć to w akcji w tym codepen:
https://codepen.io/ColinEberhardt/pen/dOBvOy
gdzie możesz zmienić rozmiar okna i sprawdzić, czy wykres jest poprawnie ponownie renderowany.
Pamiętaj, że jako pełne ujawnienie jestem jednym z opiekunów d3fc.
źródło
Unikałbym zmiany rozmiaru / zaznaczenia rozwiązań, takich jak plaga, ponieważ są one nieefektywne i mogą powodować problemy w Twojej aplikacji (np. Etykietka ponownie oblicza pozycję, w jakiej powinna się wyświetlać przy zmianie rozmiaru okna, a chwilę później zmienia się również rozmiar wykresu i strona się zmienia układy, a teraz ponownie podpowiedź).
Możesz symulować to zachowanie w niektórych starszych przeglądarkach, które nie obsługują go poprawnie, np. IE11, również za pomocą
<canvas>
elementu, który zachowuje jego aspekt.Biorąc pod uwagę 960 x 540, który jest aspektem 16: 9:
źródło
Wiele skomplikowanych odpowiedzi tutaj.
Zasadniczo wszystko, co musisz zrobić, to porzucić atrybuty
width
iheight
na rzeczviewBox
atrybutu:Jeśli masz marginesy, możesz po prostu dodać je tam do szerokości / wysokości, a następnie po prostu dołączyć je
g
później i przekształcić tak, jak zwykle.źródło
Możesz także użyć bootstrap 3, aby dostosować rozmiar wizualizacji. Na przykład możemy ustawić kod HTML jako:
Ustawiłem stałą wysokość ze względu na moje potrzeby, ale możesz również pozostawić automatyczny rozmiar. „Col-sm-6 col-md-4” sprawia, że div reaguje na różne urządzenia. Możesz dowiedzieć się więcej na http://getbootstrap.com/css/#grid-example-basic
Możemy uzyskać dostęp do wykresu za pomocą identyfikatora miesięcznego widoku .
Nie będę szczegółowo omawiał kodu d3, wprowadzę tylko część potrzebną do dostosowania do różnych rozmiarów ekranu.
Szerokość jest ustawiana przez uzyskanie szerokości div z identyfikatorem widok miesiąca.
Wysokość w moim przypadku nie powinna obejmować całego obszaru. Mam też tekst nad paskiem, więc muszę też obliczyć ten obszar. Dlatego zidentyfikowałem obszar tekstu za pomocą id responsivetext. Aby obliczyć dozwoloną wysokość paska, odjąłem wysokość tekstu od wysokości div.
To pozwala ci mieć pasek, który przyjmie wszystkie różne rozmiary ekranu / div. Może nie jest to najlepszy sposób na zrobienie tego, ale z pewnością działa na potrzeby mojego projektu.
źródło