React Echarts渲染自定义Svg楼层平面图时出现错误。

huangapple go评论72阅读模式
英文:

React Echarts Error for render custom Svg floor plan

问题

I use react to visualize an SVG floor plan (heatmap) in React.js. However, it will return an error:

Cannot read properties of undefined (reading regions)

Here is your translated code:

import React, { useRef, useEffect } from "react";
import * as echarts from "echarts";
import mapData from "./map.svg";

export default function Heatmap() {
  const ref = useRef(null);

  let mapInstance = null;

  const option = {
    tooltip: {},
    visualMap: {
      left: 'center',
      bottom: '10%',
      min: 5,
      max: 100,
      orient: 'horizontal',
      text: ['', 'Price'],
      realtime: true,
      calculable: true,
      inRange: {
        color: ['#dbac00', '#db6e00', '#cf0000']
      }
    },

    series: [
      {
        name: 'French Beef Cuts',
        type: 'map',
        map: 'testing',
        roam: true,
        emphasis: {
          label: {
            show: false
          }
        },
        selectedMode: false,
        data: [
          { name: 'Queue', value: 15 },
          // ... (other data points)
          { name: 'Filet', value: 95 }
        ]
      }
    ]
  };

  const renderMap = (myChart) => {
    myChart.setOption(option);
  };

  useEffect(() => {
    fetch(mapData)
      .then((response) => response.text())
      .then((svgText) => {
        echarts.registerMap("testing", { svg: svgText });
      });

    var chartDom = document.getElementById('beef');
    var myChart = echarts.init(chartDom);
    renderMap(myChart);
  }, []);

  return (
    <div>
      <div style={{ width: "100%", height: "50vh" }} ref={ref} id='beef'></div>
    </div>
  );
}

And here is your translated SVG file:

<svg
    xmlns="http://www.w3.org/2000/svg"
    width="591"
    height="373"
    preserveAspectRatio="xMidYMid meet"
    viewBox="0 0 376 237"
>

    <g transform="translate(-7.69,10.06)">

    <path
      d="m 536.375,106.46875 c 5.2885,14.34201 10.52945,33.1769 13.78125,43.21875 -0.0655,0.0771 -0.13181,0.1476 -0.21875,0.21875 l 16.5625,0.9375 10.5,-8.5 11,-17 -13.5,-18 -38.125,-0.875 z"
      stroke="#A5A5A5" 
      stroke-width="0.75"
      stroke-linecap="round"
      fill="#FFFFFF"
      fill-rule="evenodd"
      id="path3702"
      name="Langue" 
      transform="matrix(0.6362812,0,0,0.6362812,7.6936433,-10.065285)"
    />
    
    </g>  
</svg>
英文:

I use react to visualise a Svg floor plan (heatmap) in reactjs.
However, it will return error

> cannot read properties of undefined (reading regions)

Code:

import React, { useRef, useEffect } from &quot;react&quot;;
import * as echarts from &quot;echarts&quot;;
import mapData from &quot;./map.svg&quot;;

export default function Heatmap(){

const ref = useRef(null);

let mapInstance = null;

const option = {
    tooltip: {},
    visualMap: {
    left: &#39;center&#39;,
    bottom: &#39;10%&#39;,
    min: 5,
    max: 100,
    orient: &#39;horizontal&#39;,
    text: [&#39;&#39;, &#39;Price&#39;],
    realtime: true,
    calculable: true,
    inRange: {
        color: [&#39;#dbac00&#39;, &#39;#db6e00&#39;, &#39;#cf0000&#39;]
        }
    },

series: [
  {
    name: &#39;French Beef Cuts&#39;,
    type: &#39;map&#39;,
    map: &#39;testing&#39;,
    roam: true,
    emphasis: {
      label: {
        show: false
      }
    },
    selectedMode: false,
    data: [
      { name: &#39;Queue&#39;, value: 15 },
      { name: &#39;Langue&#39;, value: 35 },
      { name: &#39;Plat de joue&#39;, value: 15 },
      { name: &#39;Gros bout de poitrine&#39;, value: 25 },
      { name: &#39;Jumeau &#224; pot-au-feu&#39;, value: 45 },
      { name: &#39;Onglet&#39;, value: 85 },
      { name: &#39;Plat de tranche&#39;, value: 25 },
      { name: &#39;Araign&#233;e&#39;, value: 15 },
      { name: &#39;G&#238;te &#224; la noix&#39;, value: 55 },
      { name: &quot;Bavette d&#39;aloyau&quot;, value: 25 },
      { name: &#39;Tende de tranche&#39;, value: 65 },
      { name: &#39;Rond de g&#238;te&#39;, value: 45 },
      { name: &#39;Bavettede de flanchet&#39;, value: 85 },
      { name: &#39;Flanchet&#39;, value: 35 },
      { name: &#39;Hampe&#39;, value: 75 },
      { name: &#39;Plat de c&#244;tes&#39;, value: 65 },
      { name: &#39;Tendron Milieu de poitrine&#39;, value: 65 },
      { name: &#39;Macreuse &#224; pot-au-feu&#39;, value: 85 },
      { name: &#39;Rumsteck&#39;, value: 75 },
      { name: &#39;Faux-filet&#39;, value: 65 },
      { name: &#39;C&#244;tes Entrec&#244;tes&#39;, value: 55 },
      { name: &#39;Basses c&#244;tes&#39;, value: 45 },
      { name: &#39;Collier&#39;, value: 85 },
      { name: &#39;Jumeau &#224; biftek&#39;, value: 15 },
      { name: &#39;Paleron&#39;, value: 65 },
      { name: &#39;Macreuse &#224; bifteck&#39;, value: 45 },
      { name: &#39;G&#238;te&#39;, value: 85 },
      { name: &#39;Aiguillette baronne&#39;, value: 65 },
      { name: &#39;Filet&#39;, value: 95 }
    ]
  }
]
}

const renderMap = (myChart) =&gt; {

    /*const renderedMapInstance = echarts.getInstanceByDom(ref.current);
    if (renderedMapInstance) {
      mapInstance = renderedMapInstance;
    } else {
      mapInstance = echarts.init(ref.current);
    }
    mapInstance.setOption(option);*/
    myChart.setOption(option)
  };
  useEffect(() =&gt; {
    fetch(mapData)
      .then((response) =&gt; response.text())
      .then((svgText) =&gt; {
        echarts.registerMap(&quot;testing&quot;, { svg: svgText });
      });
    var chartDom = document.getElementById(&#39;beef&#39;);
    var myChart = echarts.init(chartDom);
    renderMap(myChart);
  }, []);

/*

  useEffect(() =&gt; {
    window.onresize = function () {
    };
    return () =&gt; {
      mapInstance &amp;&amp; mapInstance.dispose();
    };
  }, []);  mapInstance.resize();
    
*/

  return (
    &lt;div&gt;
      &lt;div style={{ width: &quot;100%&quot;, height: &quot;50vh&quot; }} ref={ref} id=&#39;beef&#39;&gt;&lt;/div&gt;
    &lt;/div&gt;
  );
}

Svg file

&lt;svg
    xmlns=&quot;http://www.w3.org/2000/svg&quot;
    width=&quot;591&quot;
    height=&quot;373&quot;
    preserveAspectRatio=&quot;xMidYMid meet&quot;
    viewBox=&quot;0 0 376 237&quot;
&gt;

    &lt;g transform=&quot;translate(-7.69,10.06)&quot;&gt;

    &lt;path
      
      d=&quot;m 536.375,106.46875 c 5.2885,14.34201 10.52945,33.1769 13.78125,43.21875 -0.0655,0.0771 -0.13181,0.1476 -0.21875,0.21875 l 16.5625,0.9375 10.5,-8.5 11,-17 -13.5,-18 -38.125,-0.875 z&quot;
      stroke=&quot;#A5A5A5&quot; 
      stroke-width=&quot;0.75&quot;
      stroke-linecap=&quot;round&quot;
      fill=&quot;#FFFFFF&quot;
      fill-rule=&quot;evenodd&quot;
      id=&quot;path3702&quot;
      name=&quot;Langue&quot; 
      transform=&quot;matrix(0.6362812,0,0,0.6362812,7.6936433,-10.065285)&quot;
    /&gt;
    
    &lt;/g&gt;  
&lt;/svg&gt; 

答案1

得分: 1

以下是翻译好的部分:

"你显示的错误似乎是因为尝试访问(regions属性)未注册的地图而引起的。

在你的代码中,你通过主线程使用了options对象通过myChart.setOption(option),所以它总是在异步的fetch .then链之前执行;
因此,myChart.setOption(option)(它使用了它的map'testing')在echarts.registerMap('testing', ....)之前被调用。

根据你的设置,你需要将调用setOptions移动到then处理程序内部:

useEffect(() =&gt; {
fetch('./map.svg') // "map.svg"在public目录中
.then((response) =&gt; response.text())
.then((svgText) =&gt; {
echarts.registerMap('testing', { svg: svgText });
let myChart = echarts.init(document.getElementById('beef'));
myChart.setOption(option);
})
.catch(e =&gt; console.error('fetch error', e));
});

你也可以使用awaitasync,就像在这些示例中一样。

还有一些关于如何避免在已初始化的图表/容器上调用init方法的详细信息。我在这个stackblitz中包含了一个解决方案的草图,这是你代码的一个简化的工作版本。请随时分叉并在后续查询中使用它作为可重现的示例。"

英文:

The error you displayed appears to be due to attempting to access (the regions properties of) an unregistered map.

In your code, you use the options object through myChart.setOption(option) on the main thread, so it's executed always before the asynchronous fetch .then chain;
so myChart.setOption(option) (that uses its map: &#39;testing&#39;) is called before echarts.registerMap(&#39;testing&#39;, .....

Following you setting, you have to move the call to setOptions inside the then handlers:

useEffect(() =&gt; {
fetch(&#39;./map.svg&#39;) // &quot;map.svg&quot; is in the public directory
.then((response) =&gt; response.text())
.then((svgText) =&gt; {
echarts.registerMap(&#39;testing&#39;, { svg: svgText });
let myChart = echarts.init(document.getElementById(&#39;beef&#39;));
myChart.setOption(option);
})
.catch(e =&gt; console.error(&#39;fetch error&#39;, e));
});

You may also use await with async like in these examples.

There some more details on how to avoid calling the init method on an already initialized chart/container. I included a skech of a solution for those in this stackblitz which is a simplified working version of your code. Feel free to fork it and use in further enquiries as a
reproducible example.

huangapple
  • 本文由 发表于 2023年5月21日 13:24:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298403.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定