useEcharts.tsx 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. import React, { useEffect, useRef, useState } from 'react'
  2. import { EChartsOption, init, dispose, registerMap } from 'echarts'
  3. import { Empty } from 'antd'
  4. import { china } from '@/utils/dictionary'
  5. /**通用直接传入原始配置EChartsOption*/
  6. function Echarts(props: { children: EChartsOption | null, style?: { width: number | string, height: number | string } }) {
  7. const { style } = props
  8. const ref: { current: HTMLDivElement | null } = useRef(null)
  9. const [myChart, setMyChart] = useState<any>()
  10. /**创建myChart实例 */
  11. useEffect(() => {
  12. if (ref?.current && props?.children) {
  13. let myChart = init(ref.current)
  14. setMyChart(myChart)
  15. myChart.setOption(props.children);
  16. myChart.resize()
  17. }
  18. }, [ref?.current, props?.children])
  19. /**卸载myChart */
  20. useEffect(() => {
  21. return () => {
  22. if (myChart?.id) {
  23. dispose(myChart.id)
  24. }
  25. }
  26. }, [myChart?.id])
  27. return <>
  28. {
  29. props.children
  30. ?
  31. <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  32. :
  33. <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  34. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  35. </div>
  36. }
  37. </>
  38. }
  39. /**
  40. * Map粉丝统计
  41. * @param data name省名称 vlaue值
  42. * @param style width ,height
  43. */
  44. function Map(props: { data: { name: string, value: number }[], style?: { width: number | string, height: number | string } }) {
  45. const { data, style } = props
  46. const ref: { current: HTMLDivElement | null } = useRef(null)
  47. const [myChart, setMyChart] = useState<any>()
  48. /**创建myChart实例 */
  49. useEffect(() => {
  50. if (ref?.current && data.length > 0) {
  51. let myChart = init(ref.current)//初始化chart
  52. registerMap('China', require('../../public/map.json'))//获取地图数据
  53. let num: number[] = []//获取所有值方便取最大最小值
  54. let newData: any = china//处理匹配接口返回数据和地图数据的映射避免名字不同
  55. data.forEach((item: { name: string, value: number }) => {
  56. newData.forEach((data: { name: string, value: number }) => {
  57. if (item.name && data.name.indexOf(item.name) !== -1) {
  58. data.value = item.value
  59. num.push(item.value)
  60. }
  61. })
  62. })
  63. setMyChart(myChart)//存放Chart实例以备卸载
  64. myChart.setOption({//设置Chart配置
  65. /**悬浮提示 */
  66. tooltip: {
  67. trigger: 'item',
  68. formatter: '{b}:{c}'
  69. },
  70. /**右侧操作工具 */
  71. toolbox: {
  72. show: true,
  73. orient: 'vertical',
  74. right: 50,
  75. top: 'center',
  76. feature: {
  77. dataView: {
  78. readOnly: false,
  79. title: '查看详情'
  80. },
  81. restore: {
  82. title: '刷新'
  83. },
  84. saveAsImage: {
  85. title: '保存为图片'
  86. }
  87. }
  88. },
  89. /**左侧操作工具 */
  90. visualMap: {
  91. min: 0,
  92. max: Math.max(...num),
  93. text: ['High', 'Low'],
  94. realtime: false,
  95. calculable: true,
  96. top: 'middle',
  97. inRange: {
  98. color: ['lightskyblue', 'yellow', 'orangered']
  99. }
  100. },
  101. /**地图参数设置 */
  102. series: [
  103. {
  104. name: '粉丝统计',
  105. type: 'map',
  106. map: 'China', // 自定义扩展图表类型
  107. zoom: 1.2,
  108. scaleLimit: { min: 1, max: 10 },
  109. roam: true,
  110. nameProperty: 'name',
  111. data: newData,
  112. }
  113. ],
  114. });
  115. }
  116. }, [ref?.current, data])
  117. /**卸载myChart */
  118. useEffect(() => {
  119. if (data.length === 0) {
  120. if (myChart?.id) {
  121. dispose(myChart.id)
  122. }
  123. }
  124. return () => {
  125. if (myChart?.id) {
  126. dispose(myChart.id)
  127. }
  128. }
  129. }, [myChart?.id, data])
  130. return <>
  131. {
  132. data.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  133. }
  134. {
  135. data.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  136. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  137. </div>
  138. }
  139. </>
  140. }
  141. /**
  142. * 饼图总关注
  143. * @param data name 名称 value 值
  144. * @param style width,height
  145. * @param name tooltip上的名字即饼图的名字
  146. * @param centerName 饼图中心统计的名称
  147. */
  148. function PieFocus(props: {
  149. /**
  150. * @param data name 名称 value 值
  151. */
  152. data: { name: string, value: number }[],
  153. /**
  154. * @param name tooltip上的名字即饼图的名字
  155. */
  156. name: string,
  157. /**
  158. * @param centerName 饼图中心统计的名称
  159. */
  160. centerName: string,
  161. /**
  162. * @param style width,height
  163. */
  164. style?: { width: number | string, height: number | string },
  165. }) {
  166. const { data, style, name, centerName } = props
  167. const ref: { current: HTMLDivElement | null } = useRef(null)
  168. const [myChart, setMyChart] = useState<any>()
  169. /**创建myChart实例 */
  170. useEffect(() => {
  171. if (ref?.current && data.length > 0) {
  172. let myChart = init(ref.current)
  173. setMyChart(myChart)
  174. myChart.setOption({
  175. /**鼠标悬浮 */
  176. tooltip: {
  177. // trigger: 'item',
  178. // formatter: '{a} <br />{b}: {c} ({d}%)'
  179. },
  180. /**图列 */
  181. legend: {
  182. left: 'center',
  183. bottom: 0,
  184. data: data?.map((item: { name: string }) => item.name)
  185. },
  186. /**工具保存为图片 */
  187. toolbox: {
  188. right: 50,
  189. feature: {
  190. saveAsImage: {
  191. title: '保存为图片'
  192. }
  193. }
  194. },
  195. /**饼图参数 */
  196. series: [
  197. {
  198. name,
  199. type: 'pie',
  200. radius: ['50%', '70%'],
  201. // avoidLabelOverlap: false,
  202. label: {
  203. show: true,
  204. // position: 'center',
  205. // fontSize: '30',
  206. // fontWeight: 'bold',
  207. formatter: `{b}:{c} ({d}%)`,
  208. },
  209. data
  210. },
  211. {
  212. name,
  213. type: 'pie',
  214. radius: ['50%', '70%'],
  215. label: {
  216. show: true,
  217. position: 'center',
  218. fontSize: '30',
  219. fontWeight: 'bold',
  220. formatter: `${data.length > 1 ? data?.reduce((a: any, b: { value: number }) => {
  221. return (a?.value || a) + (b?.value || 0)
  222. }) : data[0].value}\n${centerName}`,
  223. },
  224. data
  225. }
  226. ]
  227. });
  228. }
  229. }, [ref?.current, data])
  230. /**卸载myChart */
  231. useEffect(() => {
  232. if (data.length === 0) {
  233. if (myChart?.id) {
  234. dispose(myChart?.id)
  235. }
  236. }
  237. return () => {
  238. if (myChart?.id) {
  239. dispose(myChart?.id)
  240. }
  241. }
  242. }, [myChart?.id, data])
  243. return <>
  244. {
  245. data.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  246. }
  247. {
  248. data.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }} >
  249. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  250. </div>
  251. }
  252. </>
  253. }
  254. /**
  255. * Line 折线图
  256. * @param data legendName 图列名称 y:x(key为Y轴的展示的名称,value对应X轴的值。例:{legendName:'取消关注','2020-12-12':10,'2020-12-13':11,'2020-12-14':33}[])
  257. * @param style width,height
  258. */
  259. function Line(props: {
  260. data?: { legendName: string, [key: string]: any }[],
  261. style?: React.CSSProperties,
  262. areaStyle?: boolean,//线变块颜色
  263. color?: string | string[],//线颜色
  264. markPoint?: any,//浮点
  265. fontColor?: string,//文字颜色
  266. series?: boolean,//堆叠
  267. title?: string,//标题
  268. smooth?: boolean,//true 圆弧线 false 直角
  269. }) {
  270. const { data, style, areaStyle = false, color, markPoint, fontColor, series, title, smooth = false } = props
  271. const ref: { current: HTMLDivElement | null } = useRef(null)
  272. const [myChart, setMyChart] = useState<any>()
  273. let textStyle = fontColor ? { textStyle: { color: fontColor } } : {}
  274. /**创建myChart实例 */
  275. useEffect(() => {
  276. if (ref?.current && (data as any[]).length > 0) {
  277. let Xdata: any = []
  278. let Ydatas: any[] = []
  279. data?.forEach((item, index) => {
  280. Ydatas.push([])
  281. Object.keys(item).forEach((key: string) => {
  282. if (index === 0 && key !== 'legendName') {
  283. Xdata.push(key)
  284. }
  285. if (key !== 'legendName') {
  286. Ydatas[index].push(item[key])
  287. }
  288. })
  289. })
  290. let myChart = init(ref.current)
  291. setMyChart(myChart)
  292. myChart.setOption({
  293. /**鼠标悬浮 */
  294. tooltip: {
  295. trigger: 'axis'
  296. },
  297. /**图列 */
  298. legend: {
  299. data: (data as { legendName: string, [key: string]: any }[]).map((item: { legendName: string }) => item.legendName),
  300. bottom: 0,
  301. left: 'center',
  302. ...textStyle
  303. },
  304. xAxis: {
  305. data: Xdata,
  306. boundaryGap: false,//贴边
  307. },
  308. yAxis: [
  309. {
  310. type: 'value',
  311. },
  312. ],
  313. grid: {
  314. left: 100,
  315. right: 50,
  316. },
  317. ...textStyle,
  318. /**工具保存为图片 */
  319. toolbox: {
  320. right: 50,
  321. feature: {
  322. saveAsImage: {
  323. title: '保存为图片'
  324. }
  325. }
  326. },
  327. title: {
  328. text: title || '',
  329. textAlign: 'center',
  330. right: 'center'
  331. },
  332. /**线图参数 */
  333. series: (data as { legendName: string, [key: string]: any }[]).map((item: { legendName: string }, index: number) => {
  334. return {
  335. name: item.legendName,//名称
  336. type: 'line',//图形
  337. data: Ydatas[index],//数据
  338. areaStyle: areaStyle ? {} : undefined,//是否开启块级颜色
  339. color: Array.isArray(color) ? color[index] : color,//颜色
  340. markPoint: {//最大值最小值
  341. data: markPoint ? markPoint : []
  342. },
  343. emphasis: series ? { focus: 'series' } : {}, //堆叠
  344. smooth
  345. }
  346. })
  347. });
  348. }
  349. }, [ref?.current, data])
  350. /**卸载myChart */
  351. useEffect(() => {
  352. if ((data as any[])?.length === 0) {
  353. if (myChart?.id) {
  354. dispose(myChart?.id)
  355. }
  356. }
  357. return () => {
  358. if (myChart?.id) {
  359. dispose(myChart.id)
  360. }
  361. }
  362. }, [myChart?.id, data])
  363. return <>
  364. {
  365. (data as any[])?.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  366. }
  367. {
  368. (data as any[])?.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  369. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  370. </div>
  371. }
  372. </>
  373. }
  374. /**
  375. * Bar 柱状图
  376. * @param data legendName 图列名称 y:x(key为Y轴的展示的名称,value对应X轴的值。例:{legendName:'取消关注','2020-12-12':10,'2020-12-13':11,'2020-12-14':33}[])
  377. * @param style width,height
  378. */
  379. function Bar(props: {
  380. data?: { legendName: string, [key: string]: any }[],
  381. style?: React.CSSProperties,
  382. fontColor?: string,//文字颜色
  383. title?: string,//标题
  384. }) {
  385. const { data, style, fontColor, title } = props
  386. const ref: { current: HTMLDivElement | null } = useRef(null)
  387. const [myChart, setMyChart] = useState<any>()
  388. let textStyle = fontColor ? { textStyle: { color: fontColor } } : {}
  389. /**创建myChart实例 */
  390. useEffect(() => {
  391. if (ref?.current && (data as any[]).length > 0) {
  392. let Xdata: any = [] // name
  393. let Ydatas: any[] = [] // value
  394. data?.forEach((item) => {
  395. Xdata.push(item.name)
  396. Ydatas.push(item.value)
  397. })
  398. let sum = eval(Ydatas.join("+"))
  399. Ydatas = Ydatas.map((item: number) => {
  400. return (item / sum * 100).toFixed(0)
  401. })
  402. let myChart = init(ref.current)
  403. setMyChart(myChart)
  404. myChart.setOption({
  405. /**鼠标悬浮 */
  406. // tooltip: {
  407. // trigger: 'axis',
  408. // },
  409. xAxis: {
  410. max: 'dataMax'
  411. },
  412. yAxis: {
  413. type: 'category',
  414. data: Xdata,
  415. inverse: true
  416. },
  417. grid: {
  418. left: 100,
  419. right: 50,
  420. },
  421. ...textStyle,
  422. title: {
  423. text: title || '',
  424. textAlign: 'center',
  425. right: 'center'
  426. },
  427. /**线图参数 */
  428. series: [
  429. {
  430. type: 'bar',//图形
  431. realtimeSort: true,
  432. data: Ydatas,//数据
  433. name: 'X',
  434. label: {
  435. show: true,
  436. position: 'right',
  437. valueAnimation: true,
  438. }
  439. }
  440. ]
  441. });
  442. }
  443. }, [ref?.current, data])
  444. /**卸载myChart */
  445. useEffect(() => {
  446. if ((data as any[])?.length === 0) {
  447. if (myChart?.id) {
  448. dispose(myChart?.id)
  449. }
  450. }
  451. return () => {
  452. if (myChart?.id) {
  453. dispose(myChart.id)
  454. }
  455. }
  456. }, [myChart?.id, data])
  457. return <>
  458. {
  459. (data as any[])?.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  460. }
  461. {
  462. (data as any[])?.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  463. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  464. </div>
  465. }
  466. </>
  467. }
  468. /**
  469. * Bar 柱状图
  470. * @param data legendName 图列名称 y:x(key为Y轴的展示的名称,value对应X轴的值。例:{legendName:'取消关注','2020-12-12':10,'2020-12-13':11,'2020-12-14':33}[])
  471. * @param style width,height
  472. */
  473. // [
  474. // { name: '4341556373', value: 300 }, { name: '4341523456', value: 240 },
  475. // ]
  476. function BarMonitor(props: {
  477. data?: { legendName: string, [key: string]: any }[],
  478. style?: React.CSSProperties,
  479. fontColor?: string,//文字颜色
  480. title?: string,//标题
  481. isGraphic?: boolean, // 是否渐变
  482. xName?: string,
  483. yName?: string,
  484. planID?: string,
  485. onChange?: (id?: string) => void,
  486. }) {
  487. const { data, style, fontColor, title, xName, yName, planID, onChange } = props
  488. const colors = ['#f8128d', '#fa40a3', '#f56db5', '#f58bc4', '#f7a1cf', '#f5b7d8', '#facee5', '#f8c8e2', '#f8d6e8', '#fae8f1']
  489. const ref: { current: HTMLDivElement | null } = useRef(null)
  490. const [myChart, setMyChart] = useState<any>()
  491. let textStyle = fontColor ? { textStyle: { color: fontColor } } : {}
  492. /**创建myChart实例 */
  493. useEffect(() => {
  494. if (ref?.current && (data as any[]).length > 0) {
  495. let Xdata: any = [] // name
  496. let Ydatas: any[] = [] // value
  497. data?.forEach((item) => {
  498. Xdata.push(item.adName)
  499. Ydatas.push(item.value)
  500. })
  501. let dataIndex = data?.findIndex((item: any) => item?.name == planID)
  502. Ydatas = Ydatas.map((item: number, index: number) => {
  503. if (dataIndex !== -1 && dataIndex === index) {
  504. return {
  505. value: item,
  506. itemStyle: {
  507. color: '#37A2FF',
  508. shadowColor: 'rgba(0, 0, 0, 0.8)',
  509. shadowBlur: 10,
  510. },
  511. }
  512. } else {
  513. return {
  514. value: item,
  515. itemStyle: {
  516. color: colors[index],
  517. }
  518. }
  519. }
  520. })
  521. let myChart = init(ref.current)
  522. setMyChart(myChart)
  523. myChart?.setOption({
  524. /**鼠标悬浮 */
  525. // tooltip: {
  526. // trigger: 'axis',
  527. // },
  528. xAxis: {
  529. name: xName || '',
  530. max: 'dataMax',
  531. nameTextStyle: { // y轴名字文字样式设置
  532. verticalAlign: "bottom",
  533. lineHeight: 5,
  534. fontWeight: 'bold',
  535. },
  536. axisLine: { // 坐标轴轴线相关设置
  537. show: true // 是否显示坐标轴轴线
  538. },
  539. },
  540. yAxis: {
  541. name: yName || '',
  542. type: 'category',
  543. data: Xdata,
  544. inverse: true,
  545. nameLocation: 'start', // y轴名字显示位置
  546. nameTextStyle: { // y轴名字文字样式设置
  547. verticalAlign: "bottom",
  548. lineHeight: 0,
  549. fontWeight: 'bold',
  550. color: '#000',
  551. padding: [0, 80, 0, 0]
  552. },
  553. nameGap: 20,
  554. triggerEvent: true,
  555. axisLabel: {//名称
  556. margin: 10,
  557. width: 80,
  558. overflow: 'truncate',
  559. ellipsis: '...',
  560. color: (value: any, index: any) => {
  561. if (index === dataIndex) {
  562. return '#f8128d'
  563. }
  564. return '#3946c3'
  565. },
  566. },
  567. },
  568. grid: {
  569. left: 100,
  570. right: 70
  571. },
  572. ...textStyle,
  573. title: {
  574. text: title || '起量广告排行榜',
  575. textStyle: {
  576. color: '#3946c3',
  577. fontSize: 16
  578. },
  579. left: '45%',
  580. top: 330,
  581. },
  582. tooltip: {
  583. show: true,
  584. // formatter:'{b0}: {c0}',
  585. formatter: function (a: any) {
  586. return `${a.marker} <strong> ${a.name} : ${a.value}</strong>`
  587. }
  588. },
  589. series: [
  590. {
  591. type: 'bar',//图形
  592. realtimeSort: true,
  593. data: Ydatas,//数据
  594. name: 'X',
  595. showBackground: true,
  596. backgroundStyle: {
  597. color: 'transparent'
  598. },
  599. label: {
  600. show: true,
  601. valueAnimation: true,
  602. position: 'right',
  603. fontSize: 14,
  604. fontWeight: 900
  605. }
  606. }
  607. ]
  608. });
  609. myChart.on('click', (params: any) => {
  610. let v = params.dataIndex
  611. let d: any = (data as any[])[v]
  612. onChange && onChange(d.name)
  613. });
  614. }
  615. }, [ref?.current, data, planID])
  616. /**卸载myChart */
  617. useEffect(() => {
  618. if ((data as any[])?.length === 0) {
  619. if (myChart?.id) {
  620. dispose(myChart?.id)
  621. }
  622. }
  623. return () => {
  624. if (myChart?.id) {
  625. dispose(myChart.id)
  626. }
  627. }
  628. }, [myChart?.id, data])
  629. return <>
  630. {
  631. (data as any[])?.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  632. }
  633. {
  634. (data as any[])?.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  635. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  636. </div>
  637. }
  638. </>
  639. }
  640. /**
  641. * Line 折线图
  642. * @param data legendName 图列名称 y:x(key为Y轴的展示的名称,value对应X轴的值。例:{legendName:'取消关注','2020-12-12':10,'2020-12-13':11,'2020-12-14':33}[])
  643. * @param style width,height
  644. */
  645. function LineMonitor(props: {
  646. data?: { legendName: string, [key: string]: any }[],
  647. style?: React.CSSProperties,
  648. areaStyle?: boolean,//线变块颜色
  649. color?: string | string[],//线颜色
  650. markPoint?: any,//浮点
  651. fontColor?: string,//文字颜色
  652. series?: boolean,//堆叠
  653. title?: string,//标题
  654. smooth?: boolean,//true 圆弧线 false 直角
  655. dataZoomInside?: boolean, // 控制是否开启滚轮缩放
  656. dataZoomSlider?: boolean, // 控制是否开启组件缩放
  657. }) {
  658. const { data, style, areaStyle = false, color, markPoint, fontColor, series, title, smooth = false, dataZoomInside, dataZoomSlider } = props
  659. const ref: { current: HTMLDivElement | null } = useRef(null)
  660. const [myChart, setMyChart] = useState<any>()
  661. let textStyle = fontColor ? { textStyle: { color: fontColor } } : {}
  662. /**创建myChart实例 */
  663. useEffect(() => {
  664. if (ref?.current && (data as any[]).length > 0) {
  665. let Xdata: any = []
  666. let Ydatas: any[] = []
  667. data?.forEach((item, index) => {
  668. Ydatas.push([])
  669. Object.keys(item).forEach((key: string) => {
  670. if (index === 0 && key !== 'legendName') {
  671. Xdata.push(key)
  672. }
  673. if (key !== 'legendName') {
  674. Ydatas[index].push(item[key])
  675. }
  676. })
  677. })
  678. let myChart = init(ref.current)
  679. // 设置是否可缩放
  680. let dataZoom = []
  681. if (dataZoomInside) {
  682. dataZoom.push({
  683. type: 'inside'
  684. })
  685. }
  686. if (dataZoomSlider) {
  687. dataZoom.push({
  688. type: 'slider',
  689. width: 200,
  690. height: 20,
  691. top: 0,
  692. left: 140,
  693. disabled: dataZoomSlider
  694. })
  695. }
  696. setMyChart(myChart)
  697. myChart.setOption({
  698. /**鼠标悬浮 */
  699. tooltip: {
  700. trigger: 'axis'
  701. },
  702. /**图列 */
  703. legend: {
  704. data: (data as { legendName: string, [key: string]: any }[]).map((item: { legendName: string }) => item.legendName),
  705. bottom: 0,
  706. left: 'center',
  707. show: data && data?.length > 1 ? true : false,//数据只有一条就隐藏
  708. ...textStyle
  709. },
  710. xAxis: {
  711. data: Xdata,
  712. boundaryGap: false,//贴边
  713. },
  714. yAxis: [
  715. {
  716. type: 'value',
  717. axisLabel: {//名称
  718. fontWeight: 900,
  719. fontSize: 15,
  720. color: '#333333',
  721. textBorderColor: '#dfdfdf',
  722. textBorderWidth: 1
  723. },
  724. },
  725. ],
  726. dataZoom,
  727. grid: {
  728. left: 100,
  729. right: 50,
  730. },
  731. ...textStyle,
  732. /**工具保存为图片 */
  733. toolbox: {
  734. right: 50,
  735. // feature: {
  736. // saveAsImage: {
  737. // title: '保存为图片'
  738. // }
  739. // }
  740. },
  741. title: {
  742. text: title || '',
  743. left: '45%',
  744. top: 330,
  745. textStyle: {
  746. color: '#3946c3',
  747. fontSize: 16
  748. },
  749. },
  750. /**线图参数 */
  751. series: (data as { legendName: string, [key: string]: any }[]).map((item: { legendName: string }, index: number) => {
  752. return {
  753. name: item.legendName,//名称
  754. type: 'line',//图形
  755. data: Ydatas[index],//数据
  756. areaStyle: areaStyle ? {} : undefined,//是否开启块级颜色
  757. color: Array.isArray(color) ? color[index] : color,//颜色
  758. markPoint: {//最大值最小值
  759. data: markPoint ? markPoint : []
  760. },
  761. emphasis: series ? { focus: 'series' } : {}, //堆叠
  762. smooth
  763. }
  764. })
  765. });
  766. }
  767. }, [ref?.current, data])
  768. /**卸载myChart */
  769. useEffect(() => {
  770. if ((data as any[])?.length === 0) {
  771. if (myChart?.id) {
  772. dispose(myChart?.id)
  773. }
  774. }
  775. return () => {
  776. if (myChart?.id) {
  777. dispose(myChart.id)
  778. }
  779. }
  780. }, [myChart?.id, data])
  781. return <>
  782. {
  783. (data as any[])?.length > 0 && <div ref={ref} style={style ? style : { width: '100%', height: '100%' }} />
  784. }
  785. {
  786. (data as any[])?.length === 0 && <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
  787. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  788. </div>
  789. }
  790. </>
  791. }
  792. /**
  793. * 常用option配置//https://echarts.apache.org/next/zh/option.html#legend
  794. * @param legend 图例组件 用于用户操作筛选图表展示的组件
  795. * @param title 图标标题
  796. * @param grid 网格控制 可在一个渲染框架中渲染多个图表 或单个图表的间距宽高等值的设定
  797. * @param xAxis grid 中的 x 轴的设置
  798. * @param yAxis grid 中的 y 轴的设置
  799. * @param tooltip 鼠标悬浮的提示组件
  800. * @param series 系列数据配置
  801. */
  802. function useEcharts() {
  803. return {
  804. Echarts,
  805. Map,
  806. PieFocus,
  807. Line,
  808. Bar,
  809. BarMonitor,
  810. LineMonitor
  811. }
  812. }
  813. export default useEcharts