Asumsikan saya memiliki skrip histogram yang membuat grafik 960 500 svg. Bagaimana cara membuat ini responsif sehingga mengubah ukuran lebar grafik dan ketinggian dinamis?
<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>
Contoh lengkap histogram gist adalah: https://gist.github.com/993912
javascript
responsive-design
d3.js
Matt Alcock
sumber
sumber
Jawaban:
Ada cara lain untuk melakukan ini yang tidak perlu menggambar ulang grafik, dan itu melibatkan memodifikasi kotak pandang dan mempertahankan atribut AtspectRatio pada
<svg>
elemen:Pembaruan 11/24/15 : sebagian besar browser modern dapat menyimpulkan rasio aspek elemen SVG dari
viewBox
, jadi Anda mungkin tidak perlu menjaga ukuran bagan up to date. Jika Anda perlu mendukung peramban yang lebih lama, Anda dapat mengubah ukuran elemen Anda ketika ukuran jendela seperti ini:Dan konten svg akan diskalakan secara otomatis. Anda dapat melihat contoh kerja ini (dengan beberapa modifikasi) di sini : cukup mengubah ukuran jendela atau panel kanan bawah untuk melihat bagaimana reaksinya.
sumber
onload
pemanggilan fungsi. Jika lebar dan tinggi svg diatur dalam html aktual dan Anda menggunakan teknik di atas, gambar tidak akan terukur.Cari 'SVG responsif' sangat mudah untuk membuat SVG responsif dan Anda tidak perlu khawatir tentang ukuran lagi.
Inilah cara saya melakukannya:
Kode CSS:
Info lebih lanjut / tutorial:
http://demosthenes.info/blog/744/Membuat-SVG-Responsive
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
sumber
Saya sudah membuat kode inti kecil untuk menyelesaikan ini.
Pola solusi umum adalah ini:
Saya juga menambahkan skrip d3.js yang diperkecil untuk kecepatan. Intinya ada di sini: https://gist.github.com/2414111
referensi kembali kode jquery:
Kode debounce:
Nikmati!
sumber
Tanpa Menggunakan ViewBox
Berikut adalah contoh solusi yang tidak bergantung pada penggunaan
viewBox
:Kuncinya adalah dalam memperbarui kisaran dari skala yang digunakan untuk menempatkan data.
Pertama, hitung rasio aspek asli Anda:
Kemudian, pada setiap mengubah ukuran, memperbarui
range
darix
dany
:Perhatikan bahwa ketinggian didasarkan pada lebar dan rasio aspek, sehingga proporsi asli Anda dipertahankan.
Terakhir, "gambar ulang" grafik - perbarui atribut yang bergantung pada salah satu
x
atauy
skala:Perhatikan bahwa dalam mengubah ukuran
rects
Anda dapat menggunakan batas atasrange
dariy
, daripada secara eksplisit menggunakan ketinggian:Tampilkan cuplikan kode
sumber
Jika Anda menggunakan d3.js hingga c3.js solusi untuk masalah respons cukup mudah:
di mana HTML yang dihasilkan terlihat seperti:
sumber
Jawaban Shawn Allen luar biasa. Tetapi Anda mungkin tidak ingin melakukan ini setiap saat. Jika Anda meng-host-nya di vida.io , Anda mendapatkan responsif otomatis untuk visualisasi svg Anda.
Anda bisa mendapatkan iframe responsif dengan kode sematan sederhana ini:
http://jsfiddle.net/dnprock/npxp3v9d/1/
Pengungkapan: saya membangun fitur ini di vida.io .
sumber
Jika Anda menggunakan pembungkus d3 seperti plottable.js , perlu diketahui bahwa solusi termudah mungkin menambahkan pendengar acara dan kemudian memanggil fungsi redraw (
redraw
dalam plottable.js). Dalam kasus plottable.js ini akan berfungsi dengan baik (pendekatan ini tidak terdokumentasi dengan baik):sumber
Seandainya orang masih mengunjungi pertanyaan ini - inilah yang bekerja untuk saya:
Lampirkan iframe di div dan gunakan css untuk menambahkan padding, katakanlah, 40% ke div itu (persentase tergantung pada rasio aspek yang Anda inginkan). Kemudian atur lebar dan tinggi iframe itu sendiri menjadi 100%.
Dalam dokumen html yang berisi bagan yang akan dimuat dalam iframe, atur lebar ke lebar div yang ditambahkan ke svg (atau ke lebar badan) dan setel rasio aspek tinggi ke lebar *.
Tulis fungsi yang memuat ulang konten iframe pada ukuran jendela, untuk menyesuaikan ukuran grafik ketika orang memutar ponsel mereka.
Contoh di sini di situs web saya: http://dirkmjk.nl/en/2016/05/embedding-d3js-charts-responsive-website
UPDATE 30 Des 2016
Pendekatan yang saya jelaskan di atas memiliki beberapa kelemahan, terutama karena tidak memperhitungkan ketinggian judul dan keterangan yang bukan bagian dari svg yang dibuat D3. Sejak itu saya menemukan apa yang saya pikir merupakan pendekatan yang lebih baik:
Contoh di sini di situs web saya: http://dirkmjk.nl/en/2016/12/embedding-d3js-charts-responsif-website-better-solution
sumber
Salah satu prinsip dasar dari penggabungan data D3 adalah idempoten. Dengan kata lain, jika Anda berulang kali mengevaluasi data-gabung dengan data yang sama, output yang diberikan sama. Oleh karena itu, selama Anda membuat bagan Anda dengan benar, berhati-hatilah dengan pilihan masuk, perbarui dan keluar - yang harus Anda lakukan ketika ukurannya berubah, adalah render ulang bagan itu secara keseluruhan.
Ada beberapa hal lain yang harus Anda lakukan, salah satunya adalah de-bouncing jendela handler ukuran untuk mencekiknya. Selain itu, daripada lebar / ketinggian hard-coding, ini harus dicapai dengan mengukur elemen yang mengandung.
Sebagai alternatif, berikut adalah bagan Anda yang dirender menggunakan d3fc , yang merupakan sekumpulan komponen D3 yang secara benar menangani penggabungan data. Ia juga memiliki bagan kartesian yang mengukurnya mengandung elemen yang membuatnya mudah untuk membuat bagan 'responsif':
Anda dapat melihatnya beraksi di codepen ini:
https://codepen.io/ColinEberhardt/pen/dOBvOy
di mana Anda dapat mengubah ukuran jendela dan memverifikasi bahwa bagan dibuat ulang dengan benar.
Harap dicatat, sebagai pengungkapan penuh, saya adalah salah satu pengelola d3fc.
sumber
Saya akan menghindari pengubahan ukuran / centang solusi seperti wabah karena tidak efisien dan dapat menyebabkan masalah pada aplikasi Anda (mis. Tooltip menghitung ulang posisi yang seharusnya muncul pada ukuran jendela, lalu sesaat kemudian grafik Anda juga mengubah ukuran dan halaman kembali tata letak dan sekarang tooltip Anda salah lagi).
Anda dapat mensimulasikan perilaku ini di beberapa browser lama yang tidak mendukung dengan benar seperti IE11 juga menggunakan
<canvas>
elemen yang mempertahankan aspek itu.Diberikan 960x540 yang merupakan aspek 16: 9:
sumber
Banyak jawaban kompleks di sini.
Pada dasarnya yang perlu Anda lakukan adalah parit
width
danheight
atribut yang mendukungviewBox
atribut:Jika Anda memiliki margin, Anda bisa menambahkannya di sana ke dalam lebar / tinggi kemudian tambahkan saja
g
dan ubahlah seperti biasa.sumber
Anda juga dapat menggunakan bootstrap 3 untuk menyesuaikan ukuran visualisasi. Misalnya, kita dapat mengatur kode HTML sebagai:
Saya telah mengatur ketinggian tetap karena kebutuhan saya, tetapi Anda dapat membiarkan ukuran otomatis juga. "Col-sm-6 col-md-4" membuat div responsif untuk perangkat yang berbeda. Anda dapat mempelajari lebih lanjut di http://getbootstrap.com/css/#grid-example-basic
Kami dapat mengakses grafik dengan bantuan id bulan-tampilan .
Saya tidak akan membahas banyak tentang kode d3, saya hanya akan memasukkan bagian yang diperlukan untuk beradaptasi dengan ukuran layar yang berbeda.
Lebar diatur dengan mendapatkan lebar div dengan tampilan bulan id.
Ketinggian dalam kasus saya tidak harus mencakup seluruh area. Saya juga memiliki beberapa teks di atas bilah jadi saya perlu menghitung area itu juga. Itu sebabnya saya mengidentifikasi area teks dengan id responsesivetext. Untuk menghitung ketinggian bar yang diizinkan, saya mengurangi ketinggian teks dari ketinggian div.
Ini memungkinkan Anda memiliki bilah yang akan mengadopsi semua ukuran layar / div yang berbeda. Ini mungkin bukan cara terbaik untuk melakukannya, tetapi pasti bekerja untuk kebutuhan proyek saya.
sumber