img-line-chart.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. <template>
  2. <div class="chart" :id="id"></div>
  3. </template>
  4. <script>
  5. import util from "@/helper/util.js";
  6. import partten from "@/helper/partten.js";
  7. import * as echarts from "echarts";
  8. export default {
  9. name: "img-line-chart",
  10. componentName: "img-line-chart",
  11. props: {
  12. width: {
  13. type: String,
  14. default: "100%",
  15. },
  16. height: {
  17. type: String,
  18. default: "13.889vh",
  19. },
  20. // 数据
  21. list: {
  22. type: Array,
  23. default: () => [
  24. {
  25. title: "日发电量",
  26. yAxisIndex: 0,
  27. value: [
  28. {
  29. text: "1",
  30. value: 1,
  31. weather: "sun",
  32. direction: "n",
  33. angle: 0,
  34. },
  35. {
  36. text: "2",
  37. value: 2,
  38. weather: "sun",
  39. direction: "s",
  40. angle: 10,
  41. },
  42. {
  43. text: "3",
  44. value: 1,
  45. weather: "sun",
  46. direction: "w",
  47. angle: 40,
  48. },
  49. {
  50. text: "4",
  51. value: 3,
  52. weather: "sun",
  53. direction: "e",
  54. angle: 80,
  55. },
  56. {
  57. text: "5",
  58. value: 3,
  59. weather: "sun",
  60. direction: "nw",
  61. angle: 120,
  62. },
  63. {
  64. text: "6",
  65. value: 3,
  66. weather: "sun",
  67. direction: "ne",
  68. angle: 150,
  69. },
  70. {
  71. text: "7",
  72. value: 3,
  73. weather: "sun",
  74. direction: "se",
  75. angle: 180,
  76. },
  77. {
  78. text: "8",
  79. value: 3,
  80. weather: "sun",
  81. direction: "sw",
  82. angle: 270,
  83. },
  84. {
  85. text: "9",
  86. value: 3,
  87. weather: "sun",
  88. direction: "sw",
  89. angle: 290,
  90. },
  91. {
  92. text: "10",
  93. value: 3,
  94. weather: "sun",
  95. direction: "sw",
  96. angle: 10,
  97. },
  98. {
  99. text: "11",
  100. value: 3,
  101. weather: "sun",
  102. direction: "sw",
  103. angle: 10,
  104. },
  105. {
  106. text: "12",
  107. value: 3,
  108. weather: "sun",
  109. direction: "sw",
  110. angle: 10,
  111. },
  112. {
  113. text: "13",
  114. value: 3,
  115. weather: "sun",
  116. direction: "sw",
  117. angle: 10,
  118. },
  119. {
  120. text: "14",
  121. value: 3,
  122. weather: "sun",
  123. direction: "sw",
  124. angle: 10,
  125. },
  126. {
  127. text: "15",
  128. value: 3,
  129. weather: "sun",
  130. direction: "sw",
  131. angle: 10,
  132. },
  133. {
  134. text: "16",
  135. value: 3,
  136. weather: "sun",
  137. direction: "sw",
  138. angle: 10,
  139. },
  140. ],
  141. },
  142. {
  143. title: "上网电量",
  144. yAxisIndex: 0,
  145. value: [
  146. {
  147. text: "1",
  148. value: 1,
  149. },
  150. {
  151. text: "2",
  152. value: 2,
  153. },
  154. {
  155. text: "3",
  156. value: 1,
  157. },
  158. {
  159. text: "4",
  160. value: 3,
  161. },
  162. ],
  163. },
  164. ],
  165. },
  166. // 单位
  167. units: {
  168. type: Array,
  169. default: () => ["(MW)"],
  170. },
  171. showLegend: {
  172. type: Boolean,
  173. default: false,
  174. },
  175. },
  176. data() {
  177. return {
  178. id: "",
  179. chart: null,
  180. color: ["#05bb4c", "#4b55ae", "#fa8c16", "#f8de5b"],
  181. imgs: {
  182. sun: require("@assets/png/weather/sun.png"),
  183. cloud: require("@assets/png/weather/cloud.png"),
  184. rain: require("@assets/png/weather/rain.png"),
  185. },
  186. directions: {
  187. n: require("@assets/png/direction/n.svg"),
  188. s: require("@assets/png/direction/s.svg"),
  189. w: require("@assets/png/direction/w.svg"),
  190. e: require("@assets/png/direction/e.svg"),
  191. nw: require("@assets/png/direction/nw.svg"),
  192. ne: require("@assets/png/direction/ne.svg"),
  193. sw: require("@assets/png/direction/sw.svg"),
  194. se: require("@assets/png/direction/se.svg"),
  195. },
  196. angles: []
  197. };
  198. },
  199. computed: {
  200. legend() {
  201. return this.list.map((t) => {
  202. return t.title;
  203. });
  204. },
  205. xdata() {
  206. return this.list[0].value.map((t) => {
  207. return t.text;
  208. });
  209. },
  210. yAxis() {
  211. let result = [
  212. {
  213. type: "value",
  214. name: "",
  215. axisLabel: {
  216. show: false,
  217. },
  218. //分格线
  219. splitLine: {
  220. show: false,
  221. },
  222. min: 0,
  223. max: 10,
  224. },
  225. ];
  226. this.units.forEach((value, index) => {
  227. result.push({
  228. type: "value",
  229. name: value,
  230. axisLabel: {
  231. formatter: "{value}",
  232. fontSize: util.vh(14),
  233. },
  234. //分格线
  235. splitLine: {
  236. lineStyle: {
  237. color: partten.getColor("gray"),
  238. type: "dashed",
  239. },
  240. },
  241. });
  242. });
  243. return result;
  244. },
  245. series() {
  246. let result = [];
  247. this.list.forEach((value, index) => {
  248. if (index == 0) {
  249. result.push({
  250. name: value.title,
  251. type: "line",
  252. smooth: true,
  253. zlevel: index,
  254. lineStyle: {
  255. normal: {
  256. color: this.color[index],
  257. width: 1,
  258. },
  259. },
  260. yAxisIndex: value.yAxisIndex,
  261. data: value.value.map((t) => {
  262. return {
  263. value: t.value,
  264. label: {
  265. show: true,
  266. position: "top",
  267. formatter: function (e) {
  268. return [" {weather| }"];
  269. },
  270. rich: {
  271. weather: {
  272. height: 15,
  273. backgroundColor: {
  274. image: this.imgs[t.weather],
  275. },
  276. },
  277. },
  278. borderWidth: 1,
  279. borderRadius: 4,
  280. padding: [4, 10],
  281. lineHeight: 26,
  282. distance: 20,
  283. },
  284. };
  285. }),
  286. });
  287. result.push({
  288. name: "风向",
  289. type: "bar",
  290. smooth: true,
  291. zlevel: 9999,
  292. lineStyle: {
  293. normal: {
  294. color: this.color[index],
  295. width: 1,
  296. },
  297. },
  298. yAxisIndex: 0,
  299. barGap: "0%",
  300. barCategoryGap: "0%",
  301. clip: false,
  302. data: value.value.map((t) => {
  303. return {
  304. value: -2,
  305. label: {
  306. show: true,
  307. position: "inside",
  308. formatter: function (e) {
  309. return [" {direction| }"];
  310. },
  311. rich: {
  312. direction: {
  313. height: 20,
  314. backgroundColor: {
  315. image: this.angles[parseInt(t.angle) % 360],
  316. },
  317. },
  318. },
  319. borderWidth: 1,
  320. borderRadius: 4,
  321. padding: [4, 10],
  322. lineHeight: 26,
  323. distance: 20,
  324. },
  325. itemStyle: {
  326. borderWidth: 1,
  327. borderColor: "#606769",
  328. color: "transparent",
  329. },
  330. };
  331. }),
  332. });
  333. } else {
  334. result.push({
  335. name: value.title,
  336. type: "line",
  337. smooth: true,
  338. zlevel: index,
  339. label: {
  340. show: false,
  341. position: "top",
  342. borderWidth: 1,
  343. borderRadius: 4,
  344. padding: [4, 10],
  345. lineHeight: 26,
  346. distance: 20,
  347. },
  348. lineStyle: {
  349. normal: {
  350. color: this.color[index],
  351. width: 1,
  352. },
  353. },
  354. yAxisIndex: value.yAxisIndex,
  355. data: value.value.map((t) => {
  356. return t.value;
  357. }),
  358. });
  359. }
  360. });
  361. return result;
  362. },
  363. },
  364. methods: {
  365. initChart() {
  366. const chart = echarts.init(this.$el);
  367. let option = {
  368. color: this.color,
  369. tooltip: {
  370. trigger: "axis",
  371. backgroundColor: "rgba(0,0,0,0.4)",
  372. textStyle: {
  373. color: "#fff",
  374. fontSize: util.vh(16),
  375. },
  376. formatter: function (params) {
  377. let str = "";
  378. for (let i = 0; i < params.length; i++) {
  379. if (params[i].seriesName == "风向") {
  380. continue;
  381. }
  382. if (i == 0) {
  383. str += `${params[i].name}<br/>${params[i].seriesName}: ${
  384. params[i].data.value ? params[i].data.value : params[i].data
  385. }<br/>`;
  386. continue;
  387. }
  388. str += `${params[i].seriesName}: ${
  389. params[i].data.value ? params[i].data.value : params[i].data
  390. }<br/>`;
  391. }
  392. return str;
  393. },
  394. },
  395. legend: {
  396. show: this.showLegend,
  397. data: this.legend,
  398. right: 56,
  399. icon: "circle",
  400. itemWidth: 6,
  401. inactiveColor: partten.getColor("gray"),
  402. textStyle: {
  403. color: partten.getColor("grayl"),
  404. fontSize: 12,
  405. },
  406. },
  407. grid: {
  408. top: 32,
  409. left: 8,
  410. right: 8,
  411. bottom: 32,
  412. containLabel: true,
  413. },
  414. xAxis: [
  415. {
  416. type: "category",
  417. // boundaryGap: false,
  418. axisLabel: {
  419. formatter: "{value}",
  420. fontSize: 14,
  421. textStyle: {
  422. color: partten.getColor("gray"),
  423. },
  424. },
  425. data: this.xdata,
  426. offset: 32,
  427. axisLine: { onZero: true },
  428. },
  429. ],
  430. yAxis: this.yAxis,
  431. series: this.series,
  432. };
  433. chart.clear();
  434. chart.setOption(option);
  435. this.resize = function () {
  436. chart.resize();
  437. };
  438. window.addEventListener("resize", this.resize);
  439. },
  440. },
  441. created() {
  442. this.id = "pie-chart-" + util.newGUID();
  443. for (let i = 0; i <= 360; i++) {
  444. this.angles.push(require(`@assets/png/angle/angle${i}.svg`));
  445. }
  446. },
  447. mounted() {
  448. this.$nextTick(() => {
  449. setTimeout(() => {
  450. this.$el.style.width = this.width;
  451. this.$el.style.height = this.height;
  452. this.initChart();
  453. }, 1000);
  454. });
  455. },
  456. updated() {
  457. this.$nextTick(() => {
  458. this.initChart();
  459. });
  460. },
  461. unmounted() {
  462. window.removeEventListener("resize", this.resize);
  463. },
  464. };
  465. </script>
  466. <style lang="less">
  467. .chart {
  468. width: 100%;
  469. height: 100%;
  470. display: inline-block;
  471. }
  472. </style>