apache / echarts

Apache ECharts is a powerful, interactive charting and data visualization library for browser
https://echarts.apache.org
Apache License 2.0
60.25k stars 19.61k forks source link

"Can't get dom width or height" incorrectly fires for width/height values of 0. #10478

Closed mixonic closed 4 years ago

mixonic commented 5 years ago

Version

4.2.1

Steps to reproduce

This warning from echarts: https://github.com/apache/incubator-echarts/blob/b6ab21159617b45c8077d998d468977cdd87d146/src/echarts.js#L1999 seems to be triggered when !dom.clientWidth, however I believe it is valid for dom.clientWidth to have a value of 0.

I'm not sure why this warning was added, but I think the check should be dom.clientWidth === undefined if the check is for a failure of the clientWidth API to exist.

What is expected?

warning should not occur for element width/height of 0

What is actually happening?

warning is logged.


I'm happy to resolve this issue, but I'd like some confirmation my hunch is correct, or a clarification for why it is not.

echarts-bot[bot] commented 5 years ago

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.

Have a nice day! 🍵

Ovilia commented 5 years ago

Why should 0 be a valid value for a container? The warning here is to warn users that the chart is not visible most likely because the container doesn't have width or height, in which case clientWidth or clientHeight is 0. Actually, they can never be undefined unless you assign so intentionally.

mixonic commented 5 years ago

@Ovilia A relative sized <div> may be 0 pixels in height or width before the chart is appended to that element. That is the case I'm getting the warning for.

The warning here is to warn users that the chart is not visible most likely because the container doesn't have width or height

The warning is specifically Can't get dom width or height. I think the original intent was to warn that a value could not be read at all, not that the chart might be invisible. For example the element in question could also be outside the screen, be visibility hidden, or display none and those things are not checked for.

But I'm not sure about original intent. Some history:

And afaict IE6 has support for clientHeight so I don't think it is an IE hack.

Ovilia commented 5 years ago

The width and height of the container are required to create a canvas with the same size. So none of 0 or null or undefined is valid when init. Although we could provide a default canvas size when container size is not given, it may cause some confusions (e.g., the user has defined canvas CSS width and height, and the size is not the same with canvas size). Perhaps we should change the warning expression to make this information more understandable. But I don't think providing a default canvas size when container size is a very good idea. Because first of all, setting container size is not a hard job for the user to do, as long as they know what's wrong here. On the other hand, providing a default value that users don't know how to change (calling resize) is a bigger problem.

aemooooon commented 3 years ago

The width and height of the container are required to create a canvas with the same size. So none of 0 or null or undefined is valid when init. Although we could provide a default canvas size when container size is not given, it may cause some confusions (e.g., the user has defined canvas CSS width and height, and the size is not the same with canvas size). Perhaps we should change the warning expression to make this information more understandable. But I don't think providing a default canvas size when container size is a very good idea. Because first of all, setting container size is not a hard job for the user to do, as long as they know what's wrong here. On the other hand, providing a default value that users don't know how to change (calling resize) is a bigger problem.

I have to say that your English is sooooo nice!

aemooooon commented 3 years ago

Version

4.2.1

Steps to reproduce

This warning from echarts: https://github.com/apache/incubator-echarts/blob/b6ab21159617b45c8077d998d468977cdd87d146/src/echarts.js#L1999 seems to be triggered when !dom.clientWidth, however I believe it is valid for dom.clientWidth to have a value of 0.

I'm not sure why this warning was added, but I think the check should be dom.clientWidth === undefined if the check is for a failure of the clientWidth API to exist.

What is expected?

warning should not occur for element width/height of 0

What is actually happening?

warning is logged.

I'm happy to resolve this issue, but I'd like some confirmation my hunch is correct, or a clarification for why it is not.

I got this warning because I using tab card, when page onload the container set by CSS with display:none . So I got this warning, but when switch the tab card, container will be assigned the width/height instead of 0. So for me just ignored this warn.

evalcraciun commented 3 years ago

if I set height: auto, i still get the warning, even if i have a default size on the container: grid: { left: '100px', bottom: '20px', height: 'auto' } I need to set height: auto because i'm using media queries, what would be the solution for this case ?

bryanmillerph commented 3 years ago

Version

4.2.1

Steps to reproduce

This warning from echarts: https://github.com/apache/incubator-echarts/blob/b6ab21159617b45c8077d998d468977cdd87d146/src/echarts.js#L1999 seems to be triggered when !dom.clientWidth, however I believe it is valid for dom.clientWidth to have a value of 0. I'm not sure why this warning was added, but I think the check should be dom.clientWidth === undefined if the check is for a failure of the clientWidth API to exist.

What is expected?

warning should not occur for element width/height of 0

What is actually happening?

warning is logged. I'm happy to resolve this issue, but I'd like some confirmation my hunch is correct, or a clarification for why it is not.

I got this warning because I using tab card, when page onload the container set by CSS with display:none . So I got this warning, but when switch the tab card, container will be assigned the width/height instead of 0. So for me just ignored this warn.

echarts-5.1.1: I was also getting this issue when a

containing the chart is initially set to display:none;

agustinclarity commented 3 years ago

Hi there! Guys, I am getting this warning:

Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0.For example, you may need to call this in the callback of window.onload.

And honestly I have tried with pretty much evertyhing:

  • Provide chart container with fixed height and width (something like 100px each).
  • Provide chart container with height and width both with auto as value.
  • Provide chart container with height and width both with 100% as value and other respective values like 100vh and 100vw.
  • Provide chart container with height and width directly from CSS.

No luck so far, I am using the latest version of ECharts and its React Wrapper and this is the only warning I was not allowed to clean.

    "echarts": "^5.1.2",
    "echarts-for-react": "^3.0.1",
    "echarts-stat": "^1.2.0",

Any help would be more than appreciated.

Thanks in advance!

lougroshek commented 3 years ago

I'm seeing this during jest testing and am providing parent width and height (and have also attempted to set window innerHeight and innerWidth in various ways). Just a warning, but would love if we could resolve somehow.

 console.warn
    Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0.For example, you may need to call this in the callback of window.onload.

      at Object.init$1 [as init] (node_modules/echarts/lib/core/echarts.js:2226:15)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.getEchartsInstance (node_modules/echarts-for-react/src/core.tsx:89:68)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.updateEChartsOption (node_modules/echarts-for-react/src/core.tsx:160:33)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.renderNewEcharts (node_modules/echarts-for-react/src/core.tsx:114:34)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.componentDidMount (node_modules/echarts-for-react/src/core.tsx:31:10)
      at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:20663:24)
      at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:23426:7)
test('Renders scatter plot ReportWidget', () => {
  window.innerWidth = 1200
  window.innerHeight = 800
  render(
    <ApolloWrapper>
      <Router>
        <ThemeProvider theme={theme}>
          <div style={{ width: '600px', height: '400px' }}>
            <ReportWidget report="scatter" />
          </div>
        </ThemeProvider>
      </Router>
    </ApolloWrapper>
  )
})

Have also tried other ways of setting window size before the test, both in beforeEach() and in the test itself:

# Global provided by jest
global.innerHeight = 800
  global.innerWidth = 1200
# Object.defineProperty
  Object.defineProperty(window, 'innerWidth', {
    writable: true,
    configurable: true,
    value: 1200,
  })
  Object.defineProperty(window, 'innerHeight', {
    writable: true,
    configurable: true,
    value: 800,
  })

echarts 5.1.2 echarts-for-react 3.0.1 jest-dom 5.14.1

hamzadigi commented 2 years ago

Same here. Any update on this?

JunlinZhu-Tommy commented 2 years ago

Same here. Any update on this?

LongToeBoy commented 2 years ago

still no update?

anthonyadamski commented 2 years ago

Any update?

just-Bri commented 2 years ago

Throwing a +1 on here.

Seeing this warning pop up when the parent container, and the div the chartRef is on, both have an initial height.

vir46 commented 2 years ago

this bug still exist?

the warning pop up still appears on me, i use this on dynamic container that doesn't have fixed width.

sometimes it appears on display: none too,,

"echarts": "^5.3.3",

JiuRanYa commented 2 years ago

this bug still exist

oleksandr-kupenko commented 2 years ago

I have tried many options. This error disappears for me only when inline styles are set for the block. Namely inline styles in absolute units. Unfortunately, calc doesn't work.

First option 1) In javascript, during initialization, add size for block using inline styles. 2) Initializing the chart. 3) Remove this style from element and execute resize for the chart if it need (For example, when changing the browser window).

const chartDiv = document.querySelector('.chartBlock');
const baseWidth = window.innerWidth - 270;
const baseHeight = window.innerHeight * 0.45;
const chart = echarts.init(chartDiv);
chart.setOption(buildChartOptions(chartData));
 chartDiv.setAttribute('style', `width: ${baseWidth}px; height: ${baseHeight}px`);
chartDiv.setAttribute('style', `width: ${null}; height: ${null}`);

//Later (when the chart is ready and if you need responsiveness)
chart.resize({
      width: 'auto',
      height: 'auto',
    });

There may be errors in the example, since I write in a framework and there is a different syntax. But the point is clear.

If you don't need responsiveness, then just add inline pixel styles to the div element.

Second option

You can simply use a timeout set to check that the block already has sizes.

  function chartCreator() {
    const chartBlockWidth = document.querySelector('.chartBlock').clientWidth;
    if (Number.isInteger(chartBlockWidth) && chartBlockWidth > 0) {
   //create chart
    } else {
      setTimeout(() => chartCreator, 100);
    }
  }
Qinao1 commented 1 year ago

如果图表显示而没数据,是数据更新了没调用,所以会出现这个问题,这是我的解决方法,在watch里面再调用一下就没这个错误了,希望对你们有所帮助,原因出在,初始化的时候

infacto commented 1 year ago

In my case, I use ECharts with Angular (not ngx-echarts). I get this warning, but the chart is correct rendered/visible. It does not matter if I use ngInit or ngAfterViewInit. I think in the very first state of component loading, the container/layout is not yet fully loaded/sized. But it's ok and no problem when using ResizeObserver (what should use ECharts build-in btw.). So the warning is annoying. We could offer an option to disable this checks/logs.

Btw. the warning is also displayed when using min-width, min-height to e.g. 1px.

renartius commented 1 year ago

I use ECharts with vue 3 and I get this warning if I don't set width and height (in that case, chart isn't rendered). When I set width AND height, chart is correct rendered and I don't get this warning.

testforworkhh commented 1 year ago

I'm seeing this during jest testing and am providing parent width and height (and have also attempted to set window innerHeight and innerWidth in various ways). Just a warning, but would love if we could resolve somehow.

 console.warn
    Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0.For example, you may need to call this in the callback of window.onload.

      at Object.init$1 [as init] (node_modules/echarts/lib/core/echarts.js:2226:15)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.getEchartsInstance (node_modules/echarts-for-react/src/core.tsx:89:68)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.updateEChartsOption (node_modules/echarts-for-react/src/core.tsx:160:33)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.renderNewEcharts (node_modules/echarts-for-react/src/core.tsx:114:34)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.componentDidMount (node_modules/echarts-for-react/src/core.tsx:31:10)
      at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:20663:24)
      at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:23426:7)
test('Renders scatter plot ReportWidget', () => {
  window.innerWidth = 1200
  window.innerHeight = 800
  render(
    <ApolloWrapper>
      <Router>
        <ThemeProvider theme={theme}>
          <div style={{ width: '600px', height: '400px' }}>
            <ReportWidget report="scatter" />
          </div>
        </ThemeProvider>
      </Router>
    </ApolloWrapper>
  )
})

Have also tried other ways of setting window size before the test, both in beforeEach() and in the test itself:

# Global provided by jest
global.innerHeight = 800
  global.innerWidth = 1200
# Object.defineProperty
  Object.defineProperty(window, 'innerWidth', {
    writable: true,
    configurable: true,
    value: 1200,
  })
  Object.defineProperty(window, 'innerHeight', {
    writable: true,
    configurable: true,
    value: 800,
  })

echarts 5.1.2 echarts-for-react 3.0.1 jest-dom 5.14.1

same problem. when running test with getByText in "App" , ECharts component returned the error "Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight." ECharts component is a child in "App". This error aborts the test.

After spending almost a day looking for a solution, I found the answer https://stackoverflow.com/a/55100373 I use vitest, and react-router-dom. My solution:

import { expect, it } from "vitest";
import * as echarts from "echarts";
import { BrowserRouter } from "react-router-dom";
import App from "@/App";

let spy: any;
beforeAll(() => {
    spy = vi.spyOn(echarts, 'getInstanceByDom')
        .mockImplementation(
            () => ({
                hideLoading: vi.fn(),
                setOption: vi.fn(),
                showLoading: `vi.fn()`
            })
        );
});
afterAll(() => {
    spy.mockRestore();
});
it('render App',  () => {
    render( <App/>, {wrapper: BrowserRouter});
    expect(screen.getByText(/I am Child1/i)).toBeInTheDocument();
});
bryan-oliveira commented 1 year ago

Any solution to this?

alexrichardsweb commented 11 months ago

Is there any update to this? I see the issue has been closed so I'll check if there is another one with a resolution

Sheepeer commented 10 months ago

+1,same issue with echarts-fo-react

Sheepeer commented 10 months ago

Solved by resizing chart like this:

const chartRef = useRef<any>(null);

useEffect(() => {
    if (chartRef.current) {
      const chartInstance = chartRef.current.getEchartsInstance();
      chartInstance.resize();
    }
}, [])

return <ReactEcharts 
    ref={chartRef} 
    ... 
/>

echarts-for-react: v3.0.2

zekraouin commented 9 months ago

in vue 3 , i have solved the issue by adding a div container with css :

madlife12327 commented 8 months ago

The lack of height and width for the component's root node causes the echars module to fail to inherit the width and height properties to the canvas.

One solution is to set the height and width of the component's root node, and the other is to manually add width and height properties to the canvas.

组件的根节点没有高度和宽度导致echars模块无法将width属性和height属性继承到canvas中. 解决办法其一是给组件的根节点设置高度和宽度,其二是手动给canvas添加width和height属性.

vandelpavel commented 7 months ago

@zekraouin I'm using vue3 too, here is a different way to handle that issue and still want to use the autoresize feature:

<template>
  <v-chart v-if="showChart" :option="myOptions" autoresize />
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import VChart from "vue-echarts";

const showChart = ref(false);

const myOptions = {
  // ...
};

onMounted(() => (showChart.value = true));
</script>
hjs801012 commented 6 months ago

I'm developing using vue3 + nuxt3 and found a new way to apply echart. For reference, ssr is set to false. (nuxt.config.ts)

The method I used was defineAsyncComponent and set it in the parent component that uses echart.

[EChartComponent.vue]

<template>
  <div class="h-full w-full">
    <VChart class="h-full w-full" :option="pieOption" />
  </div>
</template>

<script setup>
import { PieChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TitleComponent, TooltipComponent, } from 'echarts/components'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { ref } from 'vue'
import VChart from 'vue-echarts'

use([
  CanvasRenderer,
  PieChart,
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent,
])

const pieOption = ref({
  title: {
    text: 'Title Text',
    left: 'center',
    top: 'center'
  },
  tooltip: {
    trigger: 'item',
    formatter: '{a} <br/>{b} : {c} ({d}%)',
  },
  legend: {
    orient: 'horizontal',
    left: 'center',
    top: '90%',
    data: ['Direct', 'Email', 'Ad Networks', 'Video Ads', 'Search Engines'],
  },
  height: '100%',
  width: '100%',
  textStyle: {
    fontFamily: 'NanumSquareNeo'
  },
  series: [
    {
      name: 'Count',
      type: 'pie',
      radius: ['30%', '60%'],
      center: ['50%', '50%'],
      padAngle: 3,
      itemStyle: {
        borderRadius: 10
      },
      data: [
        { value: 335, name: 'Direct' },
        { value: 310, name: 'Email' },
        { value: 234, name: 'Ad Networks' },
        { value: 135, name: 'Video Ads' },
        { value: 1548, name: 'Search Engines' },
      ],

      emphasis: {
        itemStyle: {
          shadowBlur: 15,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)',
        },
      },
    },
  ],
});

</script>
<style scoped>

</style>

[Parent component using EChartComponent]

<script setup>
import {Icon} from "#components";
import { defineAsyncComponent} from "vue";
// import EChartComponent from '~/components/EChartComponent.vue';

const echart = defineAsyncComponent(() =>
  import('~/components/EChartComponent.vue')
)
</script>

<template>
  <div class="h-full flex flex-col ">
    <main class="h-full grow p-2 flex flex-col">
      <div class="flex flex-col lg:flex-row gap-2 h-full">
        <div class="lg:basis-1/2 h-full">
          <echart />
        </div>
        <div class="lg:basis-1/2 h-full">
          <echart />
        </div>
      </div>
    </main>
  </div>
</template>

<style scoped lang="scss">

</style>
bingDBdu commented 5 months ago

dame it. I got it fixed in my case. I can only guarantee that it works in my setup. But obviously, this isn't the best way, or even a good way, to handle it. We need to come up with a better solution.

it's my solution:

import ReactECharts from "echarts-for-react";

const option = {
  // ...
  // option defines
  // ...
}

<ReactECharts
      option={option}
      style={{ width: 800, height: 400, minWidth: 800, minHeight: 400 }}
    />

add the style style={{ width: 3000, height: 400, minWidth: 800, minHeight: 400 }} to give it a wight and height. refer to https://github.com/CarterLi/vue3-echarts/issues/1#issuecomment-1841623887

if you wanna make it responsive to expend the whole width, you can use "100vw" to replace 800, and you can also to use calc() function, for example "calc(100vw - 200px)"

PestoP commented 1 month ago

I'm seeing this during jest testing and am providing parent width and height (and have also attempted to set window innerHeight and innerWidth in various ways). Just a warning, but would love if we could resolve somehow.

 console.warn
    Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0.For example, you may need to call this in the callback of window.onload.

      at Object.init$1 [as init] (node_modules/echarts/lib/core/echarts.js:2226:15)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.getEchartsInstance (node_modules/echarts-for-react/src/core.tsx:89:68)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.updateEChartsOption (node_modules/echarts-for-react/src/core.tsx:160:33)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.renderNewEcharts (node_modules/echarts-for-react/src/core.tsx:114:34)
      at EChartsReact.Object.<anonymous>.EChartsReactCore.componentDidMount (node_modules/echarts-for-react/src/core.tsx:31:10)
      at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:20663:24)
      at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:23426:7)
test('Renders scatter plot ReportWidget', () => {
  window.innerWidth = 1200
  window.innerHeight = 800
  render(
    <ApolloWrapper>
      <Router>
        <ThemeProvider theme={theme}>
          <div style={{ width: '600px', height: '400px' }}>
            <ReportWidget report="scatter" />
          </div>
        </ThemeProvider>
      </Router>
    </ApolloWrapper>
  )
})

Have also tried other ways of setting window size before the test, both in beforeEach() and in the test itself:

# Global provided by jest
global.innerHeight = 800
  global.innerWidth = 1200
# Object.defineProperty
  Object.defineProperty(window, 'innerWidth', {
    writable: true,
    configurable: true,
    value: 1200,
  })
  Object.defineProperty(window, 'innerHeight', {
    writable: true,
    configurable: true,
    value: 800,
  })

echarts 5.1.2 echarts-for-react 3.0.1 jest-dom 5.14.1

same problem. when running test with getByText in "App" , ECharts component returned the error "Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight." ECharts component is a child in "App". This error aborts the test.

After spending almost a day looking for a solution, I found the answer https://stackoverflow.com/a/55100373 I use vitest, and react-router-dom. My solution:

import { expect, it } from "vitest";
import * as echarts from "echarts";
import { BrowserRouter } from "react-router-dom";
import App from "@/App";

let spy: any;
beforeAll(() => {
    spy = vi.spyOn(echarts, 'getInstanceByDom')
        .mockImplementation(
            () => ({
                hideLoading: vi.fn(),
                setOption: vi.fn(),
                showLoading: `vi.fn()`
            })
        );
});
afterAll(() => {
    spy.mockRestore();
});
it('render App',  () => {
    render( <App/>, {wrapper: BrowserRouter});
    expect(screen.getByText(/I am Child1/i)).toBeInTheDocument();
});

If it can be useful ⤵️

I just used vi.mock('echarts/core')

With a file at __mocks__/echarts/index.ts:

import { vi } from 'vitest'

export const getInstanceByDom = {
  setOption: vi.fn(),
}
devsigner-xyz commented 1 week ago

This is still happening to me, is fixed to me setting up a fixed height using CSS but it complicates responsiveness a lot.