chart.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <!DOCTYPE html>
  2. <html lang="zh-CN" style="height: 100%">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>chart</title>
  7. </head>
  8. <style>
  9. *{
  10. margin: 0;
  11. padding: 0;
  12. box-sizing: border-box;
  13. }
  14. </style>
  15. <body style="height: 100%; margin: 0">
  16. <div id="container" style="height: 100%"></div>
  17. <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  18. <script type="text/javascript" src="https://cdn.staticfile.org/echarts/5.4.2/echarts.min.js"></script>
  19. <script type="text/javascript">
  20. function getRandomColorPair() {
  21. const colorR = Math.floor(Math.random() * (220 - 50) + 50)
  22. const colorG = Math.floor(Math.random() * (220 - 50) + 50)
  23. const colorB = Math.floor(Math.random() * (220 - 50) + 50)
  24. const colorDiff = Math.floor(Math.random() * ((255 - 220) - 20) + 20)
  25. return [
  26. `rgb(${colorR}, ${colorG}, ${colorB})`,
  27. `rgb(${colorR + colorDiff}, ${colorG + colorDiff}, ${colorB + colorDiff})`
  28. ]
  29. }
  30. const rawInfo = [
  31. {
  32. name: '开埠通商',
  33. corpList: [
  34. // {
  35. // companyName: "正泰橡皮物品制造厂",
  36. // createTime: "2023-08-03 14:21:45",
  37. // creatorId: null,
  38. // creatorName: "",
  39. // description: "创办正泰橡皮物品制造厂,首创“回力”商标。",
  40. // dirCode: "",
  41. // display: null,
  42. // fileIds: "",
  43. // id: 10,
  44. // name: "刘永康",
  45. // sort: null,
  46. // stage: "开埠通商",
  47. // story: "",
  48. // updateTime: "2023-08-03 14:21:45",
  49. // }
  50. ],
  51. id: 'time-0'
  52. },
  53. {
  54. name: '曲折发展',
  55. corpList: [],
  56. id: 'time-1'
  57. },
  58. {
  59. name: '步履维艰',
  60. corpList: [],
  61. id: 'time-2'
  62. },
  63. {
  64. name: '筚路蓝缕',
  65. corpList: [],
  66. id: 'time-3'
  67. },
  68. {
  69. name: '改革开放',
  70. corpList: [],
  71. id: 'time-4'
  72. },
  73. {
  74. name: '战略负重',
  75. corpList: [],
  76. id: 'time-5'
  77. },
  78. {
  79. name: '创新驱动',
  80. corpList: [],
  81. id: 'time-6'
  82. },
  83. {
  84. name: '追梦未来',
  85. corpList: [],
  86. id: 'time-7'
  87. },
  88. ]
  89. for (const iterator of rawInfo) {
  90. iterator.color = {
  91. type: "radial",
  92. x: 0.5,
  93. y: 0.5,
  94. r: 0.5,
  95. colorStops: [
  96. {
  97. offset: 0,
  98. color: 'rgba(51, 175, 202, 0.20)'
  99. },
  100. {
  101. offset: 1,
  102. color: 'rgba(0, 157, 191, 0.7)'
  103. },
  104. ],
  105. global: false
  106. }
  107. }
  108. const nodesForRender = [
  109. {
  110. name: "历史回顾",
  111. level: 0,
  112. category: null,
  113. symbolSize: 76,
  114. itemStyle: {
  115. color: {
  116. type: "radial",
  117. x: 0.5,
  118. y: 0.5,
  119. r: 0.5,
  120. colorStops: [
  121. {
  122. offset: 0,
  123. color: "rgba(223, 201, 145, 0.2)"
  124. },
  125. {
  126. offset: 0.5,
  127. color: "rgba(223, 201, 145, 0.5)"
  128. },
  129. {
  130. offset: 1,
  131. color: "rgba(223, 201, 145, 1)"
  132. },
  133. ],
  134. global: false
  135. },
  136. borderColor: "rgba(255,236,186,1)",
  137. borderWidth: 2,
  138. shadowColor: "rgba(223, 201, 145, 1)",
  139. shadowBlur: 10
  140. },
  141. label: {
  142. position: 'inside',
  143. show: true,
  144. color: '#fff',
  145. fontSize: '16px',
  146. fontWeight: 'bold',
  147. }
  148. },
  149. ]
  150. const edgesForRender = []
  151. Promise.allSettled(rawInfo.map((timeInfoItem) => {
  152. return axios({
  153. method: 'post',
  154. url: `https://sit-shgybwg.4dage.com/api/show/history/pageList`,
  155. headers: {
  156. "Content-Type": "application/json",
  157. },
  158. data: {
  159. stage: timeInfoItem.name
  160. },
  161. }).then((res) => {
  162. return res.data.data.records
  163. }).then((res) => {
  164. timeInfoItem.corpList = res
  165. })
  166. })).then((res) => {
  167. for (const timeInfoItem of rawInfo) {
  168. nodesForRender.push({
  169. name: timeInfoItem.name,
  170. level: 1,
  171. category: timeInfoItem.name,
  172. symbolSize: 57,
  173. itemStyle: {
  174. color: timeInfoItem.color,
  175. borderColor: "rgba(0, 157, 191, 0.6)",
  176. shadowColor: "rgba(97,170,238,0.5)",
  177. shadowBlur: 15,
  178. borderColor: 'rgba(42,174,203,1)',
  179. borderWidth: 1,
  180. },
  181. label: {
  182. position: 'inside',
  183. show: true,
  184. color: '#fff',
  185. fontSize: '13px',
  186. }
  187. })
  188. edgesForRender.push({
  189. category: null,
  190. lineStyle: {
  191. normal: {
  192. color: 'rgba(42, 174, 203, 1)',
  193. },
  194. },
  195. source: '历史回顾',
  196. target: timeInfoItem.name,
  197. })
  198. for (const corpItem of timeInfoItem.corpList) {
  199. nodesForRender.push({
  200. name: corpItem.name,
  201. level: 2,
  202. idForSend: corpItem.id,
  203. category: timeInfoItem.name,
  204. symbolSize: 12,
  205. itemStyle: {
  206. borderColor: 'rgba(42, 174, 203, 1)',
  207. color: 'transparent',
  208. },
  209. select: {
  210. itemStyle: {
  211. borderColor: timeInfoItem.color.colorStops[1].color,
  212. color: timeInfoItem.color.colorStops[1].color,
  213. },
  214. },
  215. label: {
  216. position: 'right',
  217. show: true,
  218. color: '#fff',
  219. fontSize: '13px',
  220. }
  221. })
  222. edgesForRender.push({
  223. category: timeInfoItem.name,
  224. lineStyle: {
  225. normal: {
  226. color: 'rgba(42, 174, 203, 1)',
  227. },
  228. },
  229. source: timeInfoItem.name,
  230. target: corpItem.name,
  231. })
  232. }
  233. }
  234. showAll()
  235. window.parent.postMessage('fetch data done', '*')
  236. })
  237. let myChart = null
  238. var dom = document.getElementById('container');
  239. myChart = echarts.init(dom, null, {
  240. renderer: 'canvas',
  241. useDirtyRect: false
  242. });
  243. function showAll() {
  244. return showChart()
  245. }
  246. function changeTime(timeIdx) {
  247. if (Number.isInteger(timeIdx) && timeIdx >= 0) {
  248. return showChart(timeIdx)
  249. } else {
  250. console.error('[page using echart] changeTime: invalid param!', timeIdx);
  251. }
  252. }
  253. let nodesForRenderTemp = null
  254. let edgesForRenderTemp = null
  255. function showChart(timeIdx) {
  256. if (timeIdx !== undefined) {
  257. nodesForRenderTemp = nodesForRender.filter((item) => {
  258. return item.category === rawInfo[timeIdx].name
  259. })
  260. edgesForRenderTemp = edgesForRender.filter((item) => {
  261. return item.category === rawInfo[timeIdx].name
  262. })
  263. } else {
  264. nodesForRenderTemp = null
  265. edgesForRenderTemp = null
  266. }
  267. myChart.clear()
  268. myChart.setOption({
  269. animationDurationUpdate: 1500,
  270. animationEasingUpdate: 'quinticInOut',
  271. series: [
  272. {
  273. type: 'graph',
  274. layout: 'force',
  275. // 力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力,每条边的两个节点之间添加一个引力
  276. force: {
  277. initLayout: 'circular', // 进行力引导布局前的初始化布局,初始化布局会影响到力引导的效果。默认不进行任何布局,使用节点中提供的 x, y 作为节点的位置。如果不存在的话会随机生成一个位置。也可以选择使用环形布局 'circular'。
  278. // repulsion: 100, // 节点之间的斥力因子。傻逼文档把edgeLength当数组用的用法写到这上边了。
  279. repulsion: 300, // 节点之间的斥力因子。傻逼文档把edgeLength当数组用的用法写到这上边了。
  280. // gravity: 0.1, // 节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
  281. // edgeLength: [50, 400], // 把各个边的两个节点之间的距离归一化到这个范围内。与repulsion共同作用。
  282. edgeLength: 100, // 把各个边的两个节点之间的距离归一化到这个范围内。与repulsion共同作用。
  283. layoutAnimation: true,
  284. friction: 0.5, // 这个参数能减缓节点的移动速度。取值范围 0 到 1。但是仍然是个试验性的参数,参见 #11024。
  285. },
  286. data: timeIdx === undefined ? nodesForRender : nodesForRenderTemp,
  287. // 或者叫edges
  288. links: timeIdx === undefined ? edgesForRender : edgesForRenderTemp,
  289. // 单选or多选or不可选
  290. selectedMode: 'single',
  291. // 选中时的图形样式
  292. select: {
  293. itemStyle: {
  294. shadowBlur: 30,
  295. shadowColor: 'rgba(255, 255, 125, 0.7)',
  296. },
  297. label: {
  298. fontWeight: 'bold',
  299. },
  300. },
  301. // hover时的图形样式
  302. emphasis: {
  303. scale: false,
  304. },
  305. // hover时只照常显示有联系的那些节点和边,其余的暗色显示。
  306. focusNodeAdjacency: true,
  307. // 图表是否可以移动、缩放
  308. roam: true,
  309. scaleLimit: {
  310. min: 0.5, //最小的缩放值
  311. max: 3, //最大的缩放值
  312. },
  313. draggable: true,
  314. lineStyle: {
  315. normal: {
  316. width: 1.5,
  317. curveness: 0,
  318. type: "solid"
  319. }
  320. },
  321. edgeSymbol: ["circle", "arrow"],
  322. edgeSymbolSize: [1, 8],
  323. }
  324. ]
  325. }, true)
  326. }
  327. // 用户选中节点后,向父窗口post message
  328. function onSelect(params) {
  329. if (params.dataType !== 'node') {
  330. return
  331. }
  332. window.parent.postMessage({
  333. msg: `node-selected`,
  334. nodeLevel: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].level : nodesForRender[params.dataIndexInside].level,
  335. nodeStageName: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].category : nodesForRender[params.dataIndexInside].category,
  336. nodeStageIdx: rawInfo.findIndex((item) => {
  337. return item.name === (nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].category : nodesForRender[params.dataIndexInside].category)
  338. }),
  339. nodeId: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].idForSend : nodesForRender[params.dataIndexInside].idForSend,
  340. }, '*')
  341. }
  342. myChart.on('select', onSelect)
  343. window.addEventListener('resize', myChart.resize);
  344. </script>
  345. </body>
  346. </html>