Highcharts: لا تقوم Flex container بتغيير حجم المخططات بشكل صحيح ، إذا كان لديك العديد من المخططات داخل حاوية مرنة واحدة.

تم إنشاؤها على ٢ مارس ٢٠١٧  ·  18تعليقات  ·  مصدر: highcharts/highcharts

سلوك متوقع

إذا كان لديك حاوية مرنة مع css
عرض: فليكس ؛
الاتجاه المرن: صف.

و 4 أطفال مع
نمو المرن: 1 ؛
قاعدة مرنة
تتوقع أن يكون لديك صف واحد مع 4 مخططات ، كل حجم 25٪ من الأصل.

السلوك الفعلي

يعتمد السلوك الفعلي على حجم الوالد الذي قد يكون عليه
4 عناصر في صف واحد بنسبة 25٪ (السلوك المتوقع)
3 عناصر صغيرة الحجم في صف واحد و 100٪ عنصر في الصف التالي.
4 صفوف بها 100٪ عناصر بداخلها.

عرض حي مع خطوات لإعادة الإنتاج

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

المستعرض (المستعرضات) المتأثرة

كروم
ثعلب النار

Undecided

التعليق الأكثر فائدة

تضمين التغريدة
حسنًا ، svg عبارة عن رسومات متجهة. هذا يعني أن وضع عرض SVG وارتفاعه إلى 100٪ يجب ألا يكون له أي تأثير سيء على العرض ، صححني إذا كنت مخطئًا.

تمكنت من تجاوز CSS الداخلي لعرض العنصر svg :

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

إنه يعمل بشكل جيد بشكل معقول الآن.

ال 18 كومينتر

في العرض التوضيحي الخاص بك ، أضفت مقتطفًا لتشغيل chart.reflow() بعد تغيير حجم الصندوق المرن. يعد هذا ضروريًا ، نظرًا لأن المخططات يتم إعادة تدفقها تلقائيًا فقط عند تغيير حجم _window_.

إضافةً إلى ذلك ، فإن إضافة overflow: hidden إلى حاويات المخطط يضمن أن الحاوية يمكن أن تكون أصغر من المخطط ، مما يمنعها من أن تكون واسعة جدًا عند تصغيرها.

هل هذا يحل مشكلتك؟ http://jsfiddle.net/xLz8tcrc/2/

شكرا لردك.
يبدو استخدام chart.reflow () كحل بديل أكثر من كونه إصلاحًا للمشكلة الأصلية. سيكون الأمر أبسط بكثير إذا تم تغيير حجم HighCharts بشكل صحيح وفقًا لقواعد CSS للعنصر الأصل.

لقد قمت بنشر مثال فقط ، في حالة الاستخدام الحقيقي ، نريد تغيير حجم المخططات عند تغيير حجم النافذة أو تغيير حجم العنصر الأصلي ، لذلك ليس من السهل تنفيذ المنطق حيث يمكنك استدعاء chart.reflow (). بالنسبة لتغيير حجم Window ، يكون الأمر أقل وضوحًا ، فقط باستخدام حدث تغيير حجم النافذة.
بالنسبة للمكونات الأخرى ، نحتاج إلى تنفيذ نوع من واجهة يمكن تغيير حجمها لمكون رئيسي ، حتى نتمكن من استدعاء chart.reflow عند تغيير الحجم ، والذي قد يعمل في بعض الحالات ، ولكن لست متأكدًا منها جميعًا.

هل يمكنك من فضلك عدم إغلاق التذكرة في الوقت الحالي ، سأحاول تنفيذ نهجك أو ربما لدى شخص ما أفكار أخرى.

ما تصفه هو في الأساس نفس المشكلة التي نواجهها داخليًا في Highcharts. نقوم حاليًا بإجراء عمليات إعادة تدفق تلقائية عند تغيير حجم النافذة. من الناحية المثالية ، نود إجراء عمليات إعادة تدفق تلقائية عند احتواء تغيير حجم العنصر أيضًا ، ولكن لا توجد حاليًا طريقة فعالة للاستماع إلى تغييرات حجم عنصر DOM.

راجع http://stackoverflow.com/questions/6492683/how-to-detect-divs-dimension-changed للمناقشة ، وقد تمت مناقشة نفس الموضوع مسبقًا في هذا المنتدى أيضًا. كما هو مذكور في الموضوع ، يبدو أن الطريقة الوحيدة الممكنة حاليًا هي استخدام setTimeout أو requestAnimationFrame ، وكلاهما يهدر وحدة المعالجة المركزية.

هل ألقيت نظرة على ResizeSensor المذكور في منشور StackOverflow الذي قمت بربطه بـ (https://github.com/marcj/css-element-queries)؟ يستخدم عنصرين إضافيين من عناصر DOM ومستمع أحداث scroll لاكتشاف تغيير الحجم. يستخدم فقط requestAnimationFrame لتحديد عدد أحداث تغيير الحجم التي يتم إرسالها (بحد أقصى 1 لكل إطار).

يوجد أيضًا http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ الذي يصف كيفية تحقيق ذلك باستخدام علامة object ، والتي صدفة إطلاق حدث resize عندما يتغير حجمه.

في المستقبل ، سيتم تطبيق ResizeObserver في المتصفحات ولكن هذا غير ممكن في الوقت الحالي. هناك العديد من polyfills لذلك مُدرج في https://github.com/WICG/ResizeObserver/issues/3 ولكن يبدو أنهم يعتمدون على MutationObeserver والاقتراع أو أساليب أخرى مهدرة.

في رأيي ، لا ينبغي على Highcharts تنفيذ حيل مثل هذه في جوهرها. يغطي مستمع تغيير حجم النافذة معظم الحالات ، ثم لدينا الخطاف chart.reflow للسماح للمنفذين بتغطية الحالات الأخرى ، عندما يتم تغيير حجم عنصر دون تغيير حجم النافذة. لذلك إذا اختبرت أحد الأساليب المذكورة أعلاه وعملت في حالتك ، أقترح عليك استخدام ذلك مع chart.reflow .

+1 لقد وصلنا للتو إلى هذه المشكلة ، واستغرقنا وقتًا طويلاً حتى أدركنا أن المشكلة كانت في flexbox.

أحد الأسباب التي تجعلني أتوقف عن استخدام المرن ... تغيير الحجم لا يعمل أبدًا كما هو متوقع ، نفس الهراء لشبكة العرض

عرض كتلة مضمنة أفضل بكثير

أحد الأسباب التي تجعلني أتوقف عن استخدام المرن ... تغيير الحجم لا يعمل أبدًا كما هو متوقع ، نفس الهراء لشبكة العرض

هذا مجرد حل آخر.

هل هناك أي تحديثات على هذا؟ هل هناك أي خطط لإصلاح هذا TorsteinHonsi ؟

لقد بدأت في استخدام Highcharts في مشاريع Angular وقد واجهت هذا أيضًا.
ما لم أحصل عليه هو الرسم البياني في الواقع SVG . لذلك لا ينبغي أن يكون هناك أي مشكلة في وضعه على حجم 100٪. بدلاً من ذلك ، يبدو أنه تم تعيين العرض والارتفاع صراحةً على svg.

capture

مرحبًا GeorgeKnap

هل يمكنك تقديم عرض توضيحي مباشر باستخدام Highcharts و SVG غير Highcharts لإظهار ما يدور في ذهنك؟ كيف سيؤثر هذا على القياس ودقة البكسل للعرض الحاد؟

تضمين التغريدة
حسنًا ، svg عبارة عن رسومات متجهة. هذا يعني أن وضع عرض SVG وارتفاعه إلى 100٪ يجب ألا يكون له أي تأثير سيء على العرض ، صححني إذا كنت مخطئًا.

تمكنت من تجاوز CSS الداخلي لعرض العنصر svg :

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

إنه يعمل بشكل جيد بشكل معقول الآن.

شكرا لتقاسم الحل.

تكمن مشكلة قياس SVG في أن هذا قد يتسبب في عرض ضبابي حيث يمكن فقد دقة البكسل. هناك مشكلة أخرى لحل Highcharts العام وهي دعم المتصفحات القديمة (إنه ليس مانعًا ، سنحتاج فقط إلى التأكد من أن لدينا polyfill مناسبًا).

لقد بحثت عميقًا في هذه المشكلة ووجدت ثلاث مشكلات:

  1. عند تحديد حجم الحاوية ، يستخدم Highcharts scrollWidth ، والذي يتم تقريبه في حالة أن العرض الحقيقي هو البكسل الفرعي. في الكمان الأصلي ، ينتج عن هذا الرسم البياني الأول جزء صغير من البكسل عريضًا جدًا ، ويقفز التخطيط المرن من 4 أعمدة إلى 3 أعمدة. تم إصلاح ذلك في الالتزام أعلاه باستخدام Math.floor و element.getBoundingClientRect .

  2. عند تصغير عرض الصفحة أو الحاوية ، ستكون المخططات أكبر من 25٪ المعينة لها ، وبالتالي كسر التخطيط. تم إصلاح ذلك في الالتزام أعلاه عن طريق إضافة overflow:hidden إلى حاوية مخطط المستوى الأعلى.

  3. عند زيادة حجم الحاوية المرنة لأعلى أو لأسفل _ بدون _ تغيير حجم النافذة ، لن يتم تغيير حجم المخططات. ما زالوا لا يفعلون ذلك ، لكنهم على الأقل الآن لا يكسرون التصميم. قد يعمل حل GeorgeKnap مع البعض ، ولكن كما يقول Kacper قد ينتج عنه مخططات ضبابية ، بالإضافة إلى أنه سيؤدي أيضًا إلى تغيير حجم الارتفاع ، وسيؤدي إلى عدم احترام حجم الخط وما إلى ذلك. راجع http://jsfiddle.net/highcharts/xLz8tcrc/219 / ونفس الإعداد باستخدام مكالمة صريحة chart.reflow : http://jsfiddle.net/highcharts/xLz8tcrc/221/. سيكون الحل المطلوب هو الاستماع إلى حدث ما عند تغيير حجم الحاوية div ، ولكن الحدث الأصلي الوحيد من هذا القبيل في الوقت الحالي هو Chrome ResizeObserver .

تسبب حل تجاوز CSS أعلاه في حدوث مشكلات كبيرة مع الماوس فوق موضع (تلميح الأداة). لإصلاحها ، أزلت تجاوز CSS تمامًا ونفذت ResizeObserver . يلاحظ الحجم على العنصر الأصل ويغير خصائص width و height مباشرة في خيارات الرسم البياني:

هذا هو الحل الزاوي ، لذلك يتم استخدام ElementRef للوصول إلى عنصر DOM الأصلي و ChangeDetectorRef لتشغيل فحص التغيير:

    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]);

شكرا للمشاركة! إليك مكون إضافي عام يستجيب للخيار chart.reflow ويفك ربط المعالج المدمج window.onresize إذا كان ResizeObserver مدعومًا:

// 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);
    }
});

مشاهدته مباشرة على jsFiddle .

Chart1
chart2
مرحبا،

أنا جديد في استخدام الرسوم البيانية العالية ، في لقطات الشاشة المرفقة ، يمكنك أن ترى بوضوح أن المخطط يتجاوز عرض الحاوية. لدي العديد من المخططات في نفس الصفحة والتي تفتح عندما أنقر على الأكورديون. في كل تحميل أولي ، يتجاوز عرض المخطط عرض الحاوية.
هل هناك أي حل لهذه المشكلة؟

أدناه هو رمز بخصوص الأكورديون.

function initsectionclicks (حاوية) {
$ ('. fe-section-accordion-header'، container) .click (function () {
var parentcontainer = $ (this) .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

الرجاء إضافة عرض توضيحي مباشر للمشكلة ، حتى نتمكن من إعادة إنشاء المشكلة وتصحيحها واختبار الحلول والحلول الممكنة. أيضًا ، يرجى التحقق من الحل البديل المقترح في هذا التعليق: https://github.com/highcharts/highcharts/issues/6427#issuecomment -438212322

لم يؤدي استدعاء reflow () في تغيير حجم النافذة أو استخدام المكون الإضافي إلى حل المشكلة بالنسبة لي ؛ لكن هذا الجواب من SO فعل.

أنا أستخدم مخططات عالية في حاوية bootstrap 4 flex. يتم تغيير حجم المخطط لأعلى (أوسع) ولكن لا يتم تغيير حجمه ما لم أجعل الحاوية مطلقة:

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

باستخدام CSS:

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

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

لقد أرفقت الرسم البياني بـ #chart بـ renderTo: 'chart' .

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات