英文:
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 "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 },
{ name: 'Langue', value: 35 },
{ name: 'Plat de joue', value: 15 },
{ name: 'Gros bout de poitrine', value: 25 },
{ name: 'Jumeau à pot-au-feu', value: 45 },
{ name: 'Onglet', value: 85 },
{ name: 'Plat de tranche', value: 25 },
{ name: 'Araignée', value: 15 },
{ name: 'Gîte à la noix', value: 55 },
{ name: "Bavette d'aloyau", value: 25 },
{ name: 'Tende de tranche', value: 65 },
{ name: 'Rond de gîte', value: 45 },
{ name: 'Bavettede de flanchet', value: 85 },
{ name: 'Flanchet', value: 35 },
{ name: 'Hampe', value: 75 },
{ name: 'Plat de côtes', value: 65 },
{ name: 'Tendron Milieu de poitrine', value: 65 },
{ name: 'Macreuse à pot-au-feu', value: 85 },
{ name: 'Rumsteck', value: 75 },
{ name: 'Faux-filet', value: 65 },
{ name: 'Côtes Entrecôtes', value: 55 },
{ name: 'Basses côtes', value: 45 },
{ name: 'Collier', value: 85 },
{ name: 'Jumeau à biftek', value: 15 },
{ name: 'Paleron', value: 65 },
{ name: 'Macreuse à bifteck', value: 45 },
{ name: 'Gîte', value: 85 },
{ name: 'Aiguillette baronne', value: 65 },
{ name: 'Filet', value: 95 }
]
}
]
}
const renderMap = (myChart) => {
/*const renderedMapInstance = echarts.getInstanceByDom(ref.current);
if (renderedMapInstance) {
mapInstance = renderedMapInstance;
} else {
mapInstance = echarts.init(ref.current);
}
mapInstance.setOption(option);*/
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);
}, []);
/*
useEffect(() => {
window.onresize = function () {
};
return () => {
mapInstance && mapInstance.dispose();
};
}, []); mapInstance.resize();
*/
return (
<div>
<div style={{ width: "100%", height: "50vh" }} ref={ref} id='beef'></div>
</div>
);
}
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>
答案1
得分: 1
以下是翻译好的部分:
"你显示的错误似乎是因为尝试访问(regions
属性)未注册的地图而引起的。
在你的代码中,你通过主线程使用了options
对象通过myChart.setOption(option)
,所以它总是在异步的fetch
.then
链之前执行;
因此,myChart.setOption(option)
(它使用了它的map
:'testing'
)在echarts.registerMap('testing', ....)
之前被调用。
根据你的设置,你需要将调用setOptions
移动到then
处理程序内部:
useEffect(() => {
fetch('./map.svg') // "map.svg"在public目录中
.then((response) => response.text())
.then((svgText) => {
echarts.registerMap('testing', { svg: svgText });
let myChart = echarts.init(document.getElementById('beef'));
myChart.setOption(option);
})
.catch(e => console.error('fetch error', e));
});
你也可以使用await
与async
,就像在这些示例中一样。
还有一些关于如何避免在已初始化的图表/容器上调用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
: 'testing'
) is called before echarts.registerMap('testing', ....
.
Following you setting, you have to move the call to setOptions
inside the then
handlers:
useEffect(() => {
fetch('./map.svg') // "map.svg" is in the public directory
.then((response) => response.text())
.then((svgText) => {
echarts.registerMap('testing', { svg: svgText });
let myChart = echarts.init(document.getElementById('beef'));
myChart.setOption(option);
})
.catch(e => console.error('fetch error', 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论