Mpld3: Browser/HTML menentukan ukuran gambar daripada figsize * dpi

Dibuat pada 6 Feb 2014  ·  31Komentar  ·  Sumber: mpld3/mpld3

Sangat menikmati paketnya, terima kasih banyak telah berbagi.

Ini adalah peningkatan yang disarankan, tetapi tidak cukup Pythonic. Tapi sekali lagi d3js juga tidak :)

Sangat bagus bahwa ukuran set gambar tercermin di layar, tetapi saya pikir akan "lebih responsif" untuk memiliki opsi untuk mengatur ukuran kanvas ke div pembatas, dan kemudian membiarkan ukuran div itu ditentukan oleh lebar browser/apa pun lain yang diinginkan pengembang.

Apakah layak untuk saya olok-olok di _js.py dan _object.py untuk memulai ini?

Komentar yang paling membantu

@cliffckerr Saya pasti dapat menambahkan ini ke draw_figure , mungkin sebagai argumen yang menggunakan Object dan menetapkan semua atribut yang ditentukan dalam objek itu pada svg , sehingga Anda dapat meneruskan dalam sesuatu seperti {viewBox: ..., width: '90vw', height: 'auto'} .

Saya ingin bertanya kepada Anda dan yang lainnya di utas ini apakah menurut Anda ini harus ditambahkan di tempat lain, untuk mendukung misalnya fig_to_html() . Jika demikian, mungkin kita harus memikirkan solusi untuk itu. Jika tidak, beri tahu saya dan saya dapat langsung mengubah draw_figure() .

Semua 31 komentar

Saya tidak yakin apa yang Anda tanyakan... Kami mendapatkan ukuran gambar dalam inci dari gambar matplotlib, dan juga mendapatkan dpi dari gambar matplotlib. Bagaimana Anda menyarankan kami mengubah ini? Terima kasih

Daripada menggunakan ukuran angka absolut yang disetel dengan Python, maksud saya seperti ini:

<div id='parent' class='figsizeinfo'>
//mpld3 generated code
</div>

Di mana figsizeinfo adalah spesifikasi ukuran CSS, dan mpld3 mengisi div. (dalam pengalaman saya ini adalah cara kerja flotjs)

Hmm... pertanyaan ini mungkin mengkhianati pengalaman saya dengan hal-hal web, tetapi saya pikir SVG (yang digunakan mpld3) sepenuhnya berbasis piksel, dan itu tidak dapat dengan mudah diubah. Apakah flotjs menggunakan SVG, atau spesifikasi lain?

Grafik SVG (Scalable Vector Format) berbasis vektor, bukan berbasis piksel.

Berikut adalah contoh gambar SVG yang dihasilkan dengan vanilla matplotlib yang diskalakan dengan ukuran jendela:

http://bleepshow.pithy.io/SVG_Example

(jelas meniru contoh Anda)

d3js, dan semua gambar kanvas, sejauh yang saya mengerti adalah vektor, jadi mereka harus dapat melakukan ini.

Triknya, saya bayangkan, adalah mengatur

figwidth = $(“#parent”).width //(jquery based, but you get the point )

daripada

figwidth = figsize[0] * dpi;

Ya, saya tahu bahwa SVG berbasis vektor, tetapi kecuali saya salah, ukuran kanvas, serta ukuran spidol dan posisinya di layar diukur dalam poin. Sepertinya akan sangat rumit untuk menulis kode SVG yang akan menskalakan dengan benar untuk angka arbitrer dengan ukuran jendela arbitrer.

Tidak, itu cukup mudah.

Inilah peretasan yang saya terapkan pada kode fig_to_d3 Anda:

print mpld3.fig_to_d3(fig).replace("\n","\r").replace("var figwidth = 8.0 * 80","var figwidth = $(window).width()*.9;").replace("var figheight = 6.0 * 80","var figheight = $(window).height()*.9;")

yang muncul sebagai:

http://bleepshow.pithy.io/mpld3_window_scale_test

Sekarang, label berada di tempat yang salah, tetapi sekali lagi itu "hanya" masalah referensi posisi mereka ke div dan tidak sepenuhnya ke gambar. Tapi rendering gambar bekerja dengan baik sejauh yang saya tahu.

(perhatikan bahwa ini tidak mengubah ukuran kecuali Anda menyegarkan, tetapi dengan sedikit lem yang juga lurus ke depan)

Saat ini saya sedang mencari solusi berdasarkan ini untuk diri saya sendiri, saya senang mencoba dan memolesnya menjadi sesuatu yang layak untuk permintaan tarik.

Ukuran responsif dari gambar mpld3 akan sangat berguna. Jika Anda menambahkan ini dengan tombol (di bilah alat) untuk dapat membuka gambar saat ini ke jendela baru dan seluruh gambar akan mudah diubah ukurannya.

+1

@hadim Saya ingin menyimpannya "pythonic", jadi sesuatu seperti

mpld3.fig_to_d3(fig,size="adaptive")

akan menjadi pemicu yang baik

Saya setuju !

Saya mengerti bahwa membuat gambar dengan ukuran yang berbeda itu mudah. Tapi secara keseluruhan saya masih tidak yakin itu ide yang bagus. Setelah ukuran gambar dimodifikasi, itu akan melibatkan peretasan semua lebar garis, lokasi penanda, ukuran penanda, ukuran font, dll. yang akan menambah banyak kerumitan pada kode tanpa banyak manfaat. Juga, penempatan yang benar dari legenda, label sumbu, dan properti lainnya bergantung pada perintah plt.draw() , yang membuat asumsi berdasarkan ukuran gambar internal dan pengaturan dpi, dan sejujurnya saya tidak tahu bagaimana hal itu dapat dengan mudah diubah kembali. -disesuaikan setelah fakta.

Filosofi mpld3 ini adalah untuk menghasilkan output sederhana yang mencerminkan sedekat mungkin apa yang ada di angka matplotlib. Jika Anda ingin mengubah ukuran gambar keluaran, metode yang disukai adalah menyesuaikan ukuran gambar matplotlib. Hal lain sepertinya akan dengan cepat menjadi sakit kepala besar untuk diterapkan, diuji, dan dipelihara.

Bagaimana dengan plugin?

plugins.connect(fig, plugins.ResponsiveSize())

Sebuah plugin mungkin akan menjadi cara yang baik untuk melakukannya. Tetapi sekali lagi, bagaimana Anda menangani penyesuaian ukuran font, lebar garis, ukuran penanda, lokasi legenda, dan lokasi teks sumbu? Karena semua masalah itu, tanpa infrastruktur ekstensif untuk mendukung pengubahan ukuran, saya pikir plugin semacam itu akan memiliki jangkauan kegunaan yang sangat terbatas.

@jakevdp Saya tidak setuju: satu-satunya hal yang menderita dalam peretasan 3 detik saya di atas adalah lokasi label, dan sekali lagi, ini masalah penulisan javascript yang lebih baik. DOM memungkinkan pemosisian absolut dan posisi relatif tanpa banyak pekerjaan.

Cara kode diimplementasikan sekarang, semuanya dikodekan ke dalam gambar. Dengan sedikit kerja, lebar/tinggi, ketebalan garis, dan ukuran font dapat diskalakan secara linier terhadap ukuran div. Bagian tersulit adalah rasio aspek, dan itu bisa dikunci. Setelah rasio aspek dikunci, penskalaan linier semuanya cukup mudah

@hadim itu ide yang bagus.

Saya tidak tahu d3.js jadi saya tidak tahu. Tapi karena kami sedang mengerjakan file svg, saya rasa kami tidak bisa melakukannya dengan mudah...

Beberapa tautan untuk mulai memikirkan cara terbaik untuk membuatnya:

+1 untuk @dansteingart. Mengapa tidak mengatur semua panjang dan posisi internal SVG berada dalam koordinat relatif dan kemudian sebelum output menggunakan viewBox untuk mengubah ukuran seluruh gambar dan cocok dengan parameter matplotlib figsize (atau responsif dalam kasus lain).

@dansteingart - Saya setuju bahwa dengan peretasan JS yang cukup, Anda dapat membuatnya berfungsi. Namun terlepas dari itu, saya tidak mendukung modifikasi mendasar paket ini untuk menyertakan fitur itu.

Mengapa? Yah, satu bagian adalah bahwa itu bertentangan dengan filosofi paket yang disebutkan di atas, yaitu bahwa elemen plot, ukuran gambar, dll. harus didefinisikan melalui antarmuka matplotlib.

Kedua adalah bahwa ini bukan fitur yang "harus dimiliki", dan membuat basis kode secara signifikan lebih rumit untuk fitur yang tidak harus dimiliki seperti itu akan merugikan paket dalam jangka panjang. Untuk beberapa latar belakang mengapa ini bisa terjadi, lihat pembicaraan @ellisonbg dari tahun lalu di SciPy.

Jika Anda ingin mengerjakan plugin untuk menambahkan perilaku semacam ini, silakan. Jika berfungsi dengan baik, mungkin layak untuk memasukkannya ke dalam modul plugins . Tetapi saya dengan tegas menentang modifikasi besar pada tata letak gambar dasar untuk fitur-fitur baru yang bertentangan dengan filosofi paket, tidak peduli seberapa kerennya mereka.

Saya baru saja terjebak dalam hal ini, dan bagi saya kedengarannya seperti semacam plugin dapat mencapai semacam perilaku mengubah ukuran figur responsif yang menarik. @dansteingart memulai utas ini dengan ide untuk fitur, dan pertanyaan tentang apakah layak untuk mulai mengimplementasikan fitur dengan cara tertentu. Sebagai jawaban atas pertanyaan tersebut, saya sarankan Anda memulai dengan sebuah plugin dan melihat seberapa jauh hal itu dapat berjalan tanpa mengubah _objects.py atau _js.py. Tetapi jika Anda siap untuk itu, saya ingin mengambil langkah mundur dan berbicara tentang masalah apa yang kami coba selesaikan:

Sangat bagus bahwa ukuran set gambar tercermin di layar, tetapi saya pikir akan "lebih responsif" untuk memiliki opsi untuk mengatur ukuran kanvas ke div pembatas, dan kemudian membiarkan ukuran div itu ditentukan oleh lebar browser/apa pun lain yang diinginkan pengembang.

Saya ingin beberapa klarifikasi tentang kasus penggunaan di mana ini akan muncul. Dalam alur kerja reguler saya, saya menggunakan ipython dengan server notebook yang berjalan di cloud, dengan browser web saya dimaksimalkan. Jadi itu bisa muncul untuk saya jika saya beralih dari tampilan kerja saya ke tampilan laptop saya dan memiliki lebar layar yang lebih kecil. Tapi saya yakin ada pengaturan lain yang dipikirkan orang lain. Apa lagi?

@jakevdp Cukup adil, dan saya setuju bahwa seharusnya tidak ada yang berubah _ sama sekali_ di sisi python. Namun, saya pikir itu semua permainan yang adil di sisi JS, dan jika titik percobaan adalah untuk mengawinkan aspek terbaik dari matplotlib dan d3js, saya pikir itu layak untuk dikejar.

Cara saya melihatnya, setelah Anda memanggil fig_to_d3, Anda kehabisan tanah python, dan membuat gambar responsif = menulis JS yang lebih baik.

Adapun utilitas halaman responsif, untuk output iPython saja, saya setuju dengan Anda, tetapi python lebih dari notebook iPython, dan saya pikir, pada akhirnya, menggunakan mpl3d untuk membuat halaman web responsif ukuran akan lebih berguna daripada yang Anda maksudkan di sini.

Sesuai logika Anda, jika saya ingin memperbesar detail sesuai dengan matplotlib, saya harus mengubah xlim/ylim.

Sekali lagi terima kasih untuk paket hebatnya, saya akan melihat apa yang tidak dapat saya lakukan dengan plugin dan menghubungi Anda kembali.

@aflaxman

Saya ingin beberapa klarifikasi tentang kasus penggunaan di mana ini akan muncul. Dalam alur kerja reguler saya, saya menggunakan ipython dengan server notebook yang berjalan di cloud, dengan browser web saya dimaksimalkan. Jadi itu bisa muncul untuk saya jika saya beralih dari tampilan kerja saya ke tampilan laptop saya dan memiliki lebar layar yang lebih kecil. Tapi saya yakin ada pengaturan lain yang dipikirkan orang lain. Apa lagi?

lihat http://pithy.io

Saya menulis bernas untuk memungkinkan saya/grup saya/kelas saya menulis skrip yang kemudian berubah menjadi aplikasi web. Memiliki sosok yang pas dengan jendela membuat hidup jauh lebih menyenangkan. MPL3d memberi saya alat yang jauh lebih baik untuk melakukan plot interaktif (saya meretas flot di sekitar), dan jika plot interaktif responsif terhadap ukuran, semuanya menang.

Terima kasih @dansteingart. Perlu diingat bahwa meskipun JS disembunyikan dari pengguna Python, itu tetap kode dan masih perlu dipertahankan. Pengalaman saya selama bertahun-tahun dengan pengembangan open source adalah bahwa orang-orang sering datang dengan antusias untuk mengimplementasikan fitur-fitur baru, dan setelah fitur-fitur tersebut digabungkan, pemeliharaan dan pemeliharaannya berada di pundak beberapa pengembang yang telah berinvestasi dalam paket di jangka panjang. Saya sudah sangat berkomitmen ke titik di mana saya terpaksa mengabaikan laporan bug pada paket yang digunakan dengan baik yang saya buat beberapa tahun yang lalu. Saya benar-benar tidak ingin mpld3 sampai ke titik itu.

Terima kasih atas pengertiannya, dan saya berharap dapat melihat apa yang dapat Anda kumpulkan dalam sebuah plugin.

@jakevdp poin itu diambil dengan baik, dan saya pikir arsitektur plugin berfungsi dengan baik untuk tujuan itu. Jika rusak itu akan menjadi kesalahan saya, bukan milik Anda (yaitu, kecuali jika Anda mengubah fig_to_d3 :-p )

Penulisan ulang telah mendarat, dan ini mungkin _sedikit_ lebih mudah diterapkan sebagai plugin, setidaknya untuk situasi khusus. Saya tidak menulisnya dengan situasi dinamis seperti ini, jadi mungkin ada beberapa jebakan. Beri tahu saya jika Anda membuat kemajuan dalam hal ini.

Hai, terima kasih untuk proyek hebatnya. Apakah ada kemajuan dalam masalah ini? Apakah plugin/fiturnya sudah dikembangkan? Secara khusus, saya mengacu pada "opsi untuk mengatur ukuran kanvas ke div pembatas." Terima kasih.

Saya pikir ini adalah fitur yang layak, tetapi untuk referensi setelah merencanakan Anda dapat menggunakan d3 untuk membuat gambar autoscale (di sini dengan tinggi jendela)

fetch("d3/" + figure + ".json")
    .then((response) => response.json())
    .then((data) => mpld3.draw_figure(figure, data))
    .then(() => {
        d3.select("#" + figure)
            .selectAll(".mpld3-figure")
            .attr("width", "100%")
            .attr("height", "70vh")
            .attr("viewBox", "0 0 1200 800")
            .attr("preserveAspectRatio", "xMinYMin meet");
    });

Di sini saya akan menggunakan @hadim dan @carlinmack untuk menggunakan viewBox . Ini bisa sangat sederhana sebenarnya. Misalnya, jika saat ini Anda memiliki <svg width="1200" height="800"> , coba saja <svg viewBox="0 0 1200 800"> . Itu dia. viewBox mendefinisikan sistem koordinat di dalam svg, dan parameter width dan height menjadi opsional dan mendefinisikan dimensi eksternal seperti elemen lainnya. Anda juga dapat memiliki width=100% atau menetapkan nilai melalui css secara langsung (lebar dan tinggi karena css lebih diutamakan daripada atribut).

Saya berhasil menggunakannya dengan versi chrome terbaru. Ketergantungan lintas-browser harus diselidiki untuk detailnya, tetapi saya pikir intinya jelas.

PS: ada artikel latar belakang di https://css-tricks.com/scale-svg tapi saya merasa membingungkan ketika metode yang saya uraikan di atas hanya berfungsi (setidaknya di browser modern) dan sederhana secara konseptual: viewBox = "0 0 ${width} ${height}" untuk kode dalam, width=... dan height=... sebagai atribut svg atau parameter css untuk penskalaan ulang, jika perlu.

Ya, itulah yang disarankan @carlinmack . Saya bingung dengan "gunakan d3 untuk membuat gambar skala otomatis", karena ini murni HTML/CSS, tapi ok, memanipulasi DOM adalah apa yang dilakukan d3. "preserveAspectRatio" seperti yang ditunjukkan oleh @carlinmack adalah nilai default yang saya yakini (setidaknya itulah yang dijelaskan di tautan css-tricks.com). Mengapa Anda menunjukkan height="70vh" jika rasio aspek tetap dipertahankan ? Apakah itu semacam batas atas untuk sosok yang sangat sempit dan tinggi?

benar, saya tidak ingin angka potret lebih tinggi dari viewport :)

Kecuali bahwa itu membuat angka lebih besar dari yang diperlukan, tidak sesuai ketika kecocokan yang ketat dengan konten di sekitarnya diperlukan. Menggunakan max-height sebagai gantinya bekerja untuk saya.

Inilah cara saya memuat angka mpld3 di browser:

      let figureID = "id_12345" ; 
      let dataURL = figureID + ".json" ; 

      d3.json(dataURL).then( function(data) {
        mpld3.draw_figure(figureID, data);
        return data;
      }).then( function(data) {
        d3.select("#" + figureID)
          .selectAll(".mpld3-figure")
          .attr("width", null)   // remove "width" and "height" attributes as set by mpld3
          .attr("height", null)  
          .attr("viewBox", `0 0 ${data.width} ${data.height}`)
      });

Terima kasih atas diskusinya @carlinmack @perrette ! Secara kebetulan kami juga menemukan ini, solusi @ dkong-idm adalah:

    const resizeChart = (viewBoxSettings) => {
        let svg = document.getElementsByClassName("mpld3-figure");

        if (svg && svg.length > 0) {
            svg[0].setAttribute("viewBox",viewBoxSettings );
            svg[0].setAttribute("width", "90vw");
            svg[0].setAttribute("height", "auto");
        }
    }

@vladh , apakah akan banyak pekerjaan untuk menambahkan fungsi penskalaan otomatis ini ke mpld3 , baik sebagai argumen opsional ke draw_figure atau sebagai fungsi mandiri?

@cliffckerr Saya pasti dapat menambahkan ini ke draw_figure , mungkin sebagai argumen yang menggunakan Object dan menetapkan semua atribut yang ditentukan dalam objek itu pada svg , sehingga Anda dapat meneruskan dalam sesuatu seperti {viewBox: ..., width: '90vw', height: 'auto'} .

Saya ingin bertanya kepada Anda dan yang lainnya di utas ini apakah menurut Anda ini harus ditambahkan di tempat lain, untuk mendukung misalnya fig_to_html() . Jika demikian, mungkin kita harus memikirkan solusi untuk itu. Jika tidak, beri tahu saya dan saya dapat langsung mengubah draw_figure() .

@vladh Ya, itu juga akan sangat berguna di fig_to_html() .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

jakevdp picture jakevdp  ·  4Komentar

dmiller7115 picture dmiller7115  ·  5Komentar

edvakf picture edvakf  ·  29Komentar

sheldonpark picture sheldonpark  ·  7Komentar

ledmonster picture ledmonster  ·  4Komentar