Closed yuepy closed 1 year ago
版本: "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的简单图表,渲染正常
已解决。。
能详细说一下怎么解决的么
版本: "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])
//父组件 const [data,setData] = useState([]); setTimeout(()=>{ setData(data1) },1000)