使用setNewOption渲染图表有问题
Closed this issue · 3 comments
版本:
"react-native": "0.69.3",
"react-native-echarts-pro": "1.9.0",
"react-native-webview": "^12.0.2",
"react": "18.1.0",
问题描述:静态数据option图表正常渲染,改为从父组件获取data,setNewoption更新option的方式时,不能正常渲染,option为自定义图表使用了包含 function 的renderItem,麻烦帮忙看一下
//子组件
import React,{useEffect,useRef} from 'react';
import {
View,
Dimensions,
} from 'react-native';
import RNEChartsPro from "react-native-echarts-pro";
let E_HEIGHT = Dimensions.get('window').height;
let E_WIDTH = Dimensions.get('window').width;
const colors = ['#EE4560', '#F39253', '#F9C353', '#EBDB20', '#9FE049', '#4BD3AF', '#24B9E5', '#1690FF', '#3265FE', '#6F4FF4', '#823EE0', '#D268CB'];
const SuperPie = ({data}) =>{
const pieRef = useRef()
const [option, setOption] = useState(getOption());
const [formatterData,setFormatterData] = useState(getFormatter());
useEffect(()=>{
setFormatterData(getFormatter())
},[data])
useEffect(()=>{ //更新formatterData再去更新option
if(data.length==0) return;
setOption(getOption())
},[formatterData])
useEffect(()=>{
if(!pieRef.current) return;
pieRef.current.setNewOption(option)
},[option])
//获取图表formatterVariable
function getFormatter(){
let formatterVariable = {
totalAngleValue:0,
maxRadiusValue:0,
colors:colors,
angleAcc:formatterData?formatterData.angleAcc:[],
data:data
}
for (const item of data) {
const radiusValue = item['count'] || 0
formatterVariable.totalAngleValue = formatterVariable.totalAngleValue + item['value']
formatterVariable.maxRadiusValue = Math.max(radiusValue,formatterVariable.maxRadiusValue)
}
return formatterVariable;
}
function getOption(){
if(data.length==0) return {}
let customData = []
let totalAngleValue = 0
let maxRadiusValue = 0
for (const item of data) {
const radiusValue = item['count'] || 0
customData.push([radiusValue, item['value']])
totalAngleValue = totalAngleValue + item['value']
maxRadiusValue = Math.max(radiusValue, maxRadiusValue)
}
const option = {
tooltip: {
trigger: 'item',
confine: true,
padding: 0,
textStyle:{
fontSize:8,
color:'#F00'
},
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(0,0,0,0)',
formatter:function(params){
const { dataIndex } = params
const tooltipData = formatterVariable.data[dataIndex]
const { project } = tooltipData.extra
// 交易金额需要折算为万元
let projectContent = ''
for (const item of project) {
const pCount = item.tradeCustomerCount
const pAmount = item.tradeCustomerAmount
projectContent += '<tr><td>'+item.projectName+'</td><td class="num">'+pCount+'</td><td class="num">'+pAmount+'</td></tr>'
}
const content = '<div class="g-tooltip"><div class="container"><table class="tooltip-table"><thead><tr><th></th><th>交易客户数</th><th>交易金额 (万元)</th></tr></thead><tbody><tr><td>'+tooltipData.name+'</td><td class="num">'+tooltipData.count+'</td><td class="num">'+tooltipData.value+'</td></tr>'+projectContent+'</tbody></table></div></div>'
return content;
}
},
polar: {
center: ['40%', '50%'],
//radius: [that.innerRadius, that.outerRadius]
radius: ['25%', '90%']
},
// 相当于x轴
radiusAxis: {
show: false,
type: 'value',
slient: true,
max: maxRadiusValue
},
// 相当于y轴
angleAxis: {
show: false,
type: 'value',
slient: true,
max: totalAngleValue
},
series: [
{
name: 'innerCircle',
type: 'pie',
silent: true,
center: ['40%', '50%'],
radius: ['20%', '21.5%'],
emptyCircleStyle: {
color: data.length ? 'rgba(50, 101, 254, 0.2)' : 'rgba(50,101,254,0)'
},
data: []
},
{
name: 'superPie',
type: 'custom',
coordinateSystem: 'polar',
selectedMode: 'single',
labelLayout: {
align: 'center',
verticalAlign: 'middle'
},
renderItem: function (params, api) {
//let angleAcc = []
const { dataIndex } = params
const values = [api.value(0), api.value(1)]
const coord = api.coord(values)
const size = api.size([formatterVariable.maxRadiusValue, formatterVariable.totalAngleValue], values)
const startAngle = dataIndex === 0 ? -Math.PI / 2 : formatterVariable.angleAcc[dataIndex - 1]
const endAngle = startAngle + (api.value(1) / formatterVariable.totalAngleValue) * size[1]
formatterVariable.angleAcc.push(endAngle)
// 饼图内文字角度或半径占位过小的不显示
let text = ''
if (values[1]) {
const anglePercent = (api.value(1) / formatterVariable.totalAngleValue) * 100
const radiusPercent = (api.value(0) / formatterVariable.maxRadiusValue) * 100
text = anglePercent > 5 && radiusPercent > 30 ? anglePercent.toFixed(2)+'%' : ''
}
// 校准中心label偏移问题
const targetSize = api.size(values)
let labelX = targetSize[0] / 2 - 25
if (endAngle - startAngle > endAngle) {
if (targetSize[1] > 4) {
labelX = targetSize[0] / 2 + params.coordSys.r0 / 2 + 10
} else if (targetSize[1] > 3.2) {
labelX = targetSize[0] / 2
} else if (targetSize[1] > 2) {
labelX = targetSize[0] / 2 - 10
}
} else {
if (startAngle > 3) {
labelX = 0
} else {
labelX = -15
}
}
return {
type: 'sector',
shape: {
cx: params.coordSys.cx,
cy: params.coordSys.cy,
r0: params.coordSys.r0,
r: coord[2],
startAngle,
endAngle
},
style: {
fill: formatterVariable.colors[params.dataIndex]
},
textContent: {
type: 'text',
style: {
text,
fontSize: 8,
fill: '#fff',
textAlign: 'center',
x: labelX
// y: 70
}
},
textConfig: {
position: ['50%', '50%']
},
emphasis: {
style: {
lineWidth: 1,
stroke: 'rgba(255, 255, 255, 0.8)',
shadowColor: 'rgba(7,33,91,0.9)',
shadowBlur: 32
}
},
select: {
style: {
lineWidth: 1,
stroke: 'rgba(255, 255, 255, 0.8)',
shadowColor: 'rgba(7,33,91,0.9)',
shadowBlur: 32
}
}
}
},
data: customData
}
]
}
return option
}
return(
<>
<View style={{ height: 300 }}>
<RNEChartsPro ref={pieRef} formatterVariable={formatterData} option={option} width={E_WIDTH/2} height={(E_HEIGHT-60)/7*3-40} enableParseStringFunction/>
</View>
</>
)
}
const data1 = [{
"name": "1",
"value": 17395369036.76,
"count": 6728,
"extra": {
"project": [{
"tradeCustomerCount": 4138,
"projectName": "2",
"tradeCustomerAmount": "11848075449.20"
}, {
"tradeCustomerCount": 4399,
"projectName": "3",
"tradeCustomerAmount": "2412299322.40"
}]
}
}, {
"name": "4",
"value": 7231353492.27,
"count": 3365,
"extra": {
"project": [{
"tradeCustomerCount": 1436,
"projectName": "5",
"tradeCustomerAmount": "5730715019.69"
}, {
"tradeCustomerCount": 1083,
"projectName": "6",
"tradeCustomerAmount": "1415965309.60"
}]
}
}, {
"name": "7",
"value": 1062036555.71,
"count": 1133,
"extra": {
"project": [{
"tradeCustomerCount": 1059,
"projectName": "8",
"tradeCustomerAmount": "983960642.35"
}]
}
}, {
"name": "9",
"value": 215511586.72,
"count": 767,
"extra": {
"project": [{
"tradeCustomerCount": 750,
"projectName": "10",
"tradeCustomerAmount": "202557350.22"
}, {
"tradeCustomerCount": 130,
"projectName": "11",
"tradeCustomerAmount": "12954236.50"
}]
}
}, {
"name": "12",
"value": 119211358.54,
"count": 471,
"extra": {
"project": [{
"tradeCustomerCount": 435,
"projectName": "13",
"tradeCustomerAmount": "98256735.14"
}, {
"tradeCustomerCount": 99,
"projectName": "14",
"tradeCustomerAmount": "20954623.40"
}]
}
}];
//父组件
const [data,setData] = useState([]);
setTimeout(()=>{
setData(data1)
},1000)
目前感觉可能的原因:
1.formatterVariable更新问题
2.rendItem function没有被正确的加载
尝试使用不带function的简单图表,渲染正常
已解决。。
已解决。。
能详细说一下怎么解决的么