Skip to content

Chart resize is not correct in some case of flex box layout. #11791

Open

Description

@100pah

Version

4.5.0

Steps to reproduce

Check it please: https://jsfiddle.net/6s4odwtu/

<!DOCTYPE html>


<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
    </head>
    <body>
        <style>
            .container {
                /* width: 500px; */
                display: flex;
                border: 1px solid red;
                padding: 5px;
            }
            .left {
                position: relative;
                height: 300px;
                flex: 0.5;
                border: 1px solid green;
            }
            .right {
                position: relative;
                height: 300px;
                flex: 1;
                border: 1px solid blue;
            }
            .chart {
                width: 100%;
                height: 100%;
                /* left: 0;
                top: 0; */
                position: relative;
            }
            #info {
                position: fixed;
                background: #000;
                border: 2px solid #eee;
                right: 10px;
                top: 10px;
                padding: 5px;
                width: 130px;
                height: 100px;
                color: #fff;
                box-shadow: 0 0 5px #000;
                font-size: 12px;
                z-index: 9999;
            }

        </style>

        <button id="expand">container: 700px</button>
        <button id="collapse">container: 500px</button>

        <div id="container" class="container">
            <div class="left" id="main0-box">
                <div id="main0" class="chart">
            </div>
            </div>
            <div class="right" id="main1-box">
                <div id="main1" class="chart">
            </div>

            </div>
        </div>


        <script>

            var expandBtn = document.getElementById('expand');
            var collapseBtn = document.getElementById('collapse');
            var container = document.getElementById('container');

            expandBtn.onclick = function () {
                container.style.width = '700px';
                resize();
            };
            collapseBtn.onclick = function () {
                container.style.width = '500px';
                resize();
            };

            var option;

            option0 = {
                xAxis: {},
                yAxis: {},
                series: {
                    type: 'line',
                    data: [[11, 22], [33, 44]]
                }
            };
            option1 = {
                xAxis: {},
                yAxis: {},
                series: {
                    type: 'line',
                    data: [[11, 22], [33, 44]]
                }
            };

            var main0 = document.getElementById('main0');
            var main1 = document.getElementById('main1');
            var main0Box = document.getElementById('main0-box');
            var main1Box = document.getElementById('main1-box');
            var chart0 = echarts.init(main0);
            var chart1 = echarts.init(main1);
            function resize() {
                console.log('before resize, main0Box', main0Box.offsetWidth);
                console.log('before resize, main1Box', main1Box.offsetWidth);
                chart0.resize();
                chart1.resize();
                console.log('after resize, main0Box', main0Box.offsetWidth);
                console.log('after resize, main1Box', main1Box.offsetWidth);
            };
            chart0.setOption(option0);
            chart1.setOption(option1);


        </script>


    </body>
</html>

What is expected?

Resize correct.

What is actually happening?

Resize not correct.

The reason seams to be:
echarts(zrender) set the "width/height" manually on its root dom element,
and try to set domRoot.style.display = 'none'; in Painter.js#resize.

That does not work in the case above:
If there are more than one echarts instance and the echarts element is position: relative,
set width/height and display:none one by one influence the layout of flex box.
In the above case, it firstly call chart.resize() on the first chart. And then the chart set its
domRoot.style.display = 'none';. But the second chart still have its width/height set on
its dom root. Thus the offsetWidth the first chart fetched is different from the final width of its parent dom.

So, do we really need to manually set width/height on echarts root dom in zrender?
If we do it, it might influence the layout in some cases.

Activity

  1. echarts-bot commented on Dec 5, 2019

    @echarts-bot

    Hi! We've received your issue and please be patient to get responded. 🎉
    The average response time is expected to be within one day for weekdays.

    In the meanwhile, please make sure that you have posted enough image to demo your request. You may also check out the API and chart option to get the answer.

    If you don't get helped for a long time (over a week) or have an urgent question to ask, you may also send an email to dev@echarts.apache.org. Please attach the issue link if it's a technical questions.

    If you are interested in the project, you may also subscribe our mail list.

    Have a nice day! 🍵

  2. added this to the TBD milestone on Dec 5, 2019
  3. nuragic commented on Jan 14, 2020

    @nuragic

    Hello,

    I've also found a similar (or maybe the same) problem using a chart inside a flexbox layout.

    I have a layout that contains a left column, a central container, and a right column. Both left and right columns can be toggled on/off (show/hide); the central container is where the chart is rendered.

    What I've been observing is: the width property (dynamically created CSS rule of the chart container div) increase dynamically e.g. when I hide a column in my layout; however, it doesn't decrease e.g. when I show again the same column of my layout.

    If I remove the witdh property from the dynamically created CSS rule, then it's immediately recalculated by the JS and it actually have a right value! 🤷‍♂

  4. nuragic commented on Jan 14, 2020

    @nuragic

    I've temporally solved this by setting width: auto!important from my CSS to override the width from the dynamically created CSS rule.

  5. plainheart commented on Dec 13, 2020

    @plainheart
    Member

    Probably it can work by hiding manually all root DOMs of ECharts before resizing. Just like what mentioned in #13004. But I'm not clear if we should do it in zrender.

  6. PVermeer commented on Jul 1, 2022

    @PVermeer

    Faced the same issue:
    Work around (simplified):

    new ResizeObserver(() => chart.resize()).observe(resizedElementByFlexbox);
  7. ChristopherJBarr commented on Mar 20, 2023

    @ChristopherJBarr

    I think I found a way around this. If you set the flexbox element wrapping the chart to position: relative and overflow:hidden (not needed just looks better that way). Then set the chart itself to position:absolute and 100% width and height, it seems to resize correctly.

  8. djaeger-inercomp commented on Mar 30, 2023

    @djaeger-inercomp

    @ChristopherJBarr brilliant, tried around for quite some time, then found your answer and it works straight away, thank you!

  9. AKclown commented on Oct 12, 2023

    @AKclown

    I think I found a way around this. If you set the flexbox element wrapping the chart to position: relative and overflow:hidden (not needed just looks better that way). Then set the chart itself to position:absolute and 100% width and height, it seems to resize correctly.

    Thank you so much, it works for me

  10. fireflysemantics commented on Jan 1, 2024

    @fireflysemantics
  11. fireflysemantics commented on Jan 3, 2024

    @fireflysemantics

    Since applying absolute positioning to the element that the EChart is rendered within like this this fixes it:

    div[echarts] {
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
    }
    

    Would it b e OK to just style the element that echarts is added to like this by default?

  12. fuxing2024 commented on Nov 16, 2024

    @fuxing2024

    我想我找到了解决这个问题的方法。如果你将包裹图表的弹性框元素设置为 position:relative 和 overflow:hidden(不需要,这样看起来会更好)。然后将图表本身设置为 position:absolute 和 100% 宽度和高度,它似乎可以正确调整大小。

    大哥真神了,非常有用,爆赞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugenThis issue is in Englishtopic: css grid/flexIssues about grid/flex layout in CSS

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions