Highcharts: Wadah fleksibel tidak mengubah ukuran bagan dengan benar, jika Anda memiliki beberapa bagan di dalam satu wadah fleksibel.

Dibuat pada 2 Mar 2017  ·  18Komentar  ·  Sumber: highcharts/highcharts

Perilaku yang diharapkan

Jika Anda memiliki wadah fleksibel dengan css
tampilan: fleksibel;
arah fleksibel: baris;

dan 4 anak dengan
flex-tumbuh: 1;
dasar fleksibel
Anda berharap memiliki satu baris dengan 4 bagan, masing-masing berukuran 25% dari induknya.

Perilaku sebenarnya

Perilaku sebenarnya tergantung pada ukuran induknya
4 item dalam satu baris dengan 25% (perilaku yang diharapkan)
3 item berukuran kecil dalam satu baris dan 100% item pada baris berikutnya.
4 baris dengan 100% item di dalamnya.

Demo langsung dengan langkah-langkah untuk mereproduksi

http://jsfiddle.net/xLz8tcrc/1/

Browser yang terpengaruh

Chrome
Firefox

Undecided

Komentar yang paling membantu

@KacperMadej
baik, svg adalah grafik vektor. Itu berarti menempatkan lebar dan tinggi SVG ke 100% seharusnya tidak memiliki efek buruk pada rendering, perbaiki saya jika saya salah.

Saya berhasil mengganti CSS lebar elemen svg dalam:

highcharts-chart::ng-deep {
  .highcharts-container,
  .highcharts-container svg {
     width: 100% !important;
     height: 100% !important;
  }
}

Ini bekerja dengan cukup baik sekarang.

Semua 18 komentar

Dalam demo Anda, saya menambahkan cuplikan untuk menjalankan chart.reflow() setelah mengubah ukuran kotak fleksibel. Ini diperlukan, karena bagan hanya mengalir ulang secara otomatis saat _jendela_ diubah ukurannya.

Selain itu, menambahkan overflow: hidden ke wadah bagan memastikan bahwa wadah bisa lebih kecil dari bagan, yang mencegahnya terlalu lebar saat diturunkan.

Apakah ini menyelesaikan masalah Anda? http://jsfiddle.net/xLz8tcrc/2/

Terima kasih untuk balasan Anda.
Menggunakan chart.reflow() lebih terlihat seperti solusi daripada memperbaiki masalah aslinya. Akan jauh lebih sederhana jika HighCharts akan mengubah ukuran dengan benar sesuai dengan aturan CSS dari elemen induk.

Saya telah memposting hanya sebuah contoh, dalam kasus penggunaan nyata kami ingin bagan diubah ukurannya pada pengubahan ukuran jendela atau pengubahan ukuran elemen induk, jadi tidak mudah untuk menerapkan logika di mana Anda dapat memanggil chart.reflow(). Untuk pengubahan ukuran jendela lebih mudah, hanya menggunakan acara pengubahan ukuran jendela.
Untuk komponen lain, kita perlu mengimplementasikan beberapa jenis antarmuka yang dapat diubah ukurannya untuk komponen induk, sehingga kita dapat memanggil chart.reflow pada pengubahan ukuran, yang mungkin berfungsi dalam beberapa kasus, tetapi tidak yakin tentang semuanya.

Bisakah Anda tidak menutup tiket untuk saat ini, saya akan mencoba menerapkan pendekatan Anda atau mungkin seseorang memiliki ide lain.

Apa yang Anda gambarkan pada dasarnya adalah masalah yang sama yang kami alami secara internal di Highcharts. Saat ini kami melakukan reflow otomatis pada pengubahan ukuran jendela. Idealnya kami juga ingin melakukan reflow otomatis pada pengubahan ukuran elemen yang mengandung, tetapi saat ini tidak ada cara yang efektif untuk mendengarkan perubahan ukuran elemen DOM.

Lihat http://stackoverflow.com/questions/6492683/how-to-detect-divs-dimension-changed untuk diskusi, dan topik yang sama telah dibahas sebelumnya di forum ini juga. Seperti yang disebutkan di utas, satu-satunya cara yang mungkin saat ini tampaknya menggunakan setTimeout atau requestAnimationFrame , keduanya membuang-buang CPU.

Apakah Anda telah melihat ResizeSensor yang disebutkan dalam posting StackOverflow yang Anda tautkan (https://github.com/marcj/css-element-queries)? Ini menggunakan beberapa elemen DOM tambahan dan pendengar acara scroll untuk mendeteksi perubahan ukuran. Ini hanya menggunakan requestAnimationFrame untuk membatasi berapa banyak acara pengubahan ukuran yang dikirim (maks 1 per bingkai).

Ada juga http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ yang menjelaskan cara melakukannya menggunakan tag object , yang secara tidak sengaja memicu acara resize ketika ukurannya berubah.

Di masa depan, akan ada ResizeObserver diimplementasikan di browser tetapi itu tidak layak sekarang. Ada beberapa polyfill untuk yang terdaftar di https://github.com/WICG/ResizeObserver/issues/3 tetapi mereka tampaknya bergantung pada MutationObeserver dan polling atau pendekatan boros lainnya.

Menurut pendapat saya, Highcharts seharusnya tidak menerapkan trik seperti ini di intinya. Pendengar pengubahan ukuran jendela mencakup sebagian besar kasus, lalu kami memiliki pengait chart.reflow untuk memungkinkan pelaksana menutupi kasus lain, ketika sebuah elemen diubah ukurannya tanpa pengubahan ukuran jendela. Jadi, jika Anda menguji salah satu pendekatan di atas dan berhasil untuk kasus Anda, saya sarankan Anda menggunakannya bersama dengan chart.reflow .

+1 Kami baru saja menemukan masalah ini, butuh waktu lama untuk menyadari bahwa masalahnya adalah flexbox.

salah satu alasan mengapa saya berhenti menggunakan flex ... mengubah ukuran tidak pernah berfungsi seperti yang diharapkan, omong kosong yang sama untuk kisi tampilan

tampilan blok inline jauh lebih baik

salah satu alasan mengapa saya berhenti menggunakan flex ... mengubah ukuran tidak pernah berfungsi seperti yang diharapkan, omong kosong yang sama untuk kisi tampilan

ini hanyalah solusi lain.

Apakah ada pembaruan tentang ini? Apakah ada rencana untuk memperbaiki @TorsteinHonsi ini?

Saya mulai menggunakan Highcharts dalam proyek Angular dan saya juga mengalami ini.
Yang tidak saya dapatkan adalah grafiknya sebenarnya SVG . Jadi seharusnya tidak ada masalah untuk memasukkannya ke ukuran 100%. Sebaliknya sepertinya lebar & tinggi secara eksplisit diatur langsung ke svg.

capture

Hai @GeorgeKnap

Bisakah Anda memberikan demo langsung dengan Highcharts dan SVG non-Highcharts untuk menunjukkan apa yang Anda pikirkan? Bagaimana ini akan memengaruhi penskalaan dan presisi piksel dari rendering yang tajam?

@KacperMadej
baik, svg adalah grafik vektor. Itu berarti menempatkan lebar dan tinggi SVG ke 100% seharusnya tidak memiliki efek buruk pada rendering, perbaiki saya jika saya salah.

Saya berhasil mengganti CSS lebar elemen svg dalam:

highcharts-chart::ng-deep {
  .highcharts-container,
  .highcharts-container svg {
     width: 100% !important;
     height: 100% !important;
  }
}

Ini bekerja dengan cukup baik sekarang.

Terima kasih telah berbagi solusi.

Masalah dengan penskalaan SVG adalah hal ini dapat menyebabkan rendering buram karena presisi piksel dapat hilang. Masalah lain untuk solusi Highcharts umum adalah dukungan untuk browser lawas (ini bukan pemblokir, kami hanya perlu memastikan bahwa kami memiliki polyfill yang tepat).

Saya telah mendalami masalah ini dan menemukan tiga masalah:

  1. Saat menentukan ukuran wadah, Highcharts menggunakan scrollWidth , yang dibulatkan jika lebar sebenarnya adalah subpiksel. Dalam biola asli, ini menghasilkan bagan pertama yang digambar sebagian kecil dari piksel terlalu lebar, dan tata letak fleksibel melompat dari 4 kolom ke 3 kolom. Ini diperbaiki dalam komit di atas dengan menggunakan Math.floor dan element.getBoundingClientRect .

  2. Saat memperkecil lebar halaman atau wadah, bagan akan lebih lebar dari 25% yang ditetapkan untuknya, sehingga merusak tata letak. Ini diperbaiki dalam komit di atas dengan menambahkan overflow:hidden ke wadah bagan tingkat atas.

  3. Saat menskalakan ke atas atau ke bawah wadah fleksibel _tanpa_ mengubah ukuran jendela, bagan tidak akan diskalakan. Mereka masih tidak mau, tapi setidaknya sekarang mereka tidak merusak tata letaknya. Solusi @GeorgeKnap mungkin bekerja untuk beberapa orang, tetapi seperti yang dikatakan Kacper, ini dapat menyebabkan grafik buram, ditambah itu juga akan mengubah ukuran ketinggian, itu akan mengabaikan ukuran font, dll. Lihat http://jsfiddle.net/highcharts/xLz8tcrc/219 / dan pengaturan yang sama dengan panggilan chart.reflow eksplisit: http://jsfiddle.net/highcharts/xLz8tcrc/221/. Solusi yang diinginkan adalah mendengarkan acara ketika div penampung diubah ukurannya, tetapi untuk saat ini satu-satunya acara asli seperti itu adalah ResizeObserver Chrome.

Solusi penggantian CSS saya di atas menyebabkan masalah besar dengan posisi mouse di atas (tooltip). Untuk memperbaikinya, saya menghapus CSS override sepenuhnya dan mengimplementasikan ResizeObserver . Ini mengamati ukuran pada elemen induk dan mengubah properti width dan height langsung dalam opsi bagan:

Ini adalah solusi Angular sehingga digunakan ElementRef untuk mengakses elemen DOM asli dan ChangeDetectorRef untuk memicu pemeriksaan perubahan:

    const resizeObserver = new ResizeObserver(debounce((data: Array<ResizeObserverEntry>) => {
      if (this.chartOptions) {
        const options = { ...this.chartOptions } as Highcharts.Options;
        options.chart!.height = data[0].contentRect.height;
        options.chart!.width = data[0].contentRect.width;
        this.chartOptions = options;
        this.cd.markForCheck();
      }
    }, 200));
    resizeObserver.observe(this.elementRef.nativeElement.children[0]);

Terima kasih telah berbagi! Berikut adalah plugin umum yang merespons opsi chart.reflow dan melepaskan pengendali window.onresize bawaan jika ResizeObserver didukung:

// Generic plugin that adds support for listening to container resize rather than
// window resize. As of 2018 only Chrome supports ResizeObserver.
Highcharts.wrap(Highcharts.Chart.prototype, 'setReflow', function(proceed, reflow) {

    var chart = this;

    proceed.call(this, reflow);

    if (reflow !== false && typeof ResizeObserver === 'function') {

        // Unbind window.onresize handler so we don't do double redraws
        if (this.unbindReflow) {
            this.unbindReflow();
        }

        var ro = new ResizeObserver(function () {
            chart.reflow();
        });

        ro.observe(this.renderTo);
    }
});

Lihat langsung di jsFiddle .

Chart1
chart2
Hai,

Saya baru menggunakan bagan tinggi, dalam tangkapan layar terlampir itu, Anda dapat dengan jelas melihat bahwa bagan melebihi lebar wadah. saya memiliki banyak grafik di halaman yang sama yang terbuka ketika saya mengklik akordeon. Pada setiap pemuatan awal, lebar bagan melebihi lebar wadahnya.
apakah ada solusi untuk masalah ini?

di bawah ini adalah kode tentang akordeon.

function initsectionclicks(wadah) {
$('.fe-section-accordion-header', container).klik(fungsi () {
var parentcontainer = $(ini).parent();
var accordioncontainer = $(parentcontainer).find('.fe-section-accordion-container');

        if (accordioncontainer != null)
        {
            var accordioncontainerOpen = accordioncontainer.is(':visible');

            accordioncontainer[accordioncontainerOpen ? 'slideUp' : 'slideDown'](400, "swing", function() {
                ToolkitUI.Common.ResizeIFrame();
                var highChartsWrapper = $('.fe-section-chart-wrap', accordioncontainer);
                if (highChartsWrapper.length) {
                    $.each(highChartsWrapper,
                        function(index, obj) {
                            var hcObj = $(obj).highcharts();
                            if (hcObj)
                                hcObj.reflow();
                        });
                }
            });

            if (!accordioncontainerOpen)
            {
                $(accordioncontainer).ShowLoadingInsideContainer();
            }

            $(parentcontainer).find('.fe-expandcollapse').toggleClass("fe-icon-expand", accordioncontainerOpen).toggleClass("fe-icon-collapse", !accordioncontainerOpen);
            $('.fe-section-accordion-header', parentcontainer).toggleClass('highlight', !accordioncontainerOpen);
        }

        $(window).resize();
    });

    //we have to unbind any click event handlers before attaching a new one, as without unbind we will be attaching the same handler multiple times.
    //this is because we are binding the data from the start for each tab when it is clicked, which rebinds the same method again and again.
    $('.fe-accordion-expandcollapse-all', container).unbind('click').click(function () {
        var isallopen = $(this).hasClass('fe-accordion-collapse');
        var counter = 1;
        $(this).toggleClass('fe-accordion-expand', isallopen).toggleClass('fe-accordion-collapse', !isallopen);
        $('.fe-expandcollapse', container).toggleClass('fe-icon-expand', isallopen).toggleClass('fe-icon-collapse', !isallopen);
        $('.fe-section-accordion-header', container).toggleClass('highlight', !isallopen);
        $('.fe-section-accordion-container')[isallopen ? 'slideUp' : 'slideDown'](400, "swing", function () {
            if (counter == $('.fe-section-accordion-container').length) {
                ToolkitUI.Common.ResizeIFrame();
            }
            counter++;
        });

        if (!isallopen)
        {
            $('.fe-section-accordion-container').ShowLoadingInsideContainer();

        }
        $(window).resize();
    });
};

@Nagaraj2106

Harap tambahkan demo langsung untuk masalah tersebut, sehingga kami dapat membuat ulang masalah, men-debugnya, dan menguji kemungkinan solusi dan solusi. Juga, silakan periksa solusi yang disarankan dalam komentar ini: https://github.com/highcharts/highcharts/issues/6427#issuecomment -438212322

Baik memanggil reflow() pada pengubahan ukuran jendela atau menggunakan plugin tidak menyelesaikan masalah bagi saya; namun jawaban dari SO ini.

Saya menggunakan grafik tinggi dalam wadah fleksibel bootstrap 4. Bagan diubah ukurannya (lebih lebar) tetapi tidak diubah ukurannya kecuali saya membuat wadah menjadi absolut:

<div id="chart-container">
    <div id="chart"></div>
</div>

dengan CSSnya:

#chart-container {
    position: relative;
    width: 100%;
    height: 280px;
}

#chart {
    position: absolute;
    width: 100%;
}

Saya telah melampirkan bagan ke #chart dengan renderTo: 'chart' .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat