twoline.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <template>
  2. <!-- 两条曲线封装 且需要两个websocket连接 -->
  3. <div>
  4. <div ref="testLine" style="width: 450px; height: 200px; margin: 0px auto"></div>
  5. </div>
  6. </template>
  7. <script>
  8. import {
  9. mapState
  10. } from "vuex";
  11. export default {
  12. props: {
  13. title: {
  14. type: String,
  15. default: ''
  16. },
  17. id: {
  18. type: Number,
  19. required: true
  20. },
  21. unit: {
  22. type: String,
  23. default: ''
  24. },
  25. type: {
  26. type: Array,
  27. required: true
  28. },
  29. legend: {
  30. type: Array,
  31. required: true
  32. },
  33. },
  34. data() {
  35. return {
  36. currentChartId: 1,
  37. xData: new Array(30).fill("-"),
  38. y1Data: new Array(30).fill("-"),
  39. y2Data: new Array(30).fill("-"),
  40. count: 0,
  41. myChart: null,
  42. option: {
  43. tooltip: {
  44. trigger: "axis",
  45. backgroundColor: "transparent",
  46. axisPointer: {
  47. lineStyle: {
  48. color: {
  49. type: "linear",
  50. x: 0,
  51. y: 0,
  52. x2: 0,
  53. y2: 1,
  54. colorStops: [
  55. {
  56. offset: 0,
  57. color: "rgba(126,199,255,0)", // 0% 处的颜色
  58. },
  59. {
  60. offset: 0.5,
  61. color: "rgba(126,199,255,1)", // 100% 处的颜色
  62. },
  63. {
  64. offset: 1,
  65. color: "rgba(126,199,255,0)", // 100% 处的颜色
  66. },
  67. ],
  68. global: false, // 缺省为 false
  69. },
  70. },
  71. },
  72. formatter: (p) => {
  73. let dom = `<div style="width: 79px;
  74. height: 110px;;color:#fff;position: relative;">
  75. <svg style="position: absolute;top: 50%;
  76. left: 50%;
  77. transform: translateX(-50%) translateY(-50%);" class="svg" xmlns="http://www.w3.org/2000/svg" width="100"
  78. height="111" viewBox="0 0 80 85">
  79. <defs>
  80. <style>
  81. .cls-1 {
  82. fill: #07172c;
  83. fill-opacity: 0.8;
  84. stroke: #a7d8ff;
  85. stroke-linejoin: round;
  86. stroke-opacity: 0.2;
  87. stroke-width: 1px;
  88. fill-rule: evenodd;
  89. }
  90. </style>
  91. </defs>
  92. <path id="矩形_419" data-name="矩形 419" class="cls-1" d="M266,595h74v50H266V624.046L261,620l5-3.984V595Z"
  93. transform="translate(-258.5 -592.5)" />
  94. </svg>
  95. <div style="padding: 3px 1px 3px 11px;display: flex;
  96. justify-content: center;
  97. align-items: center;
  98. flex-direction: column;position: relative;z-index: 1;">
  99. <div
  100. style="margin-bottom: 4px;width:100%;display:${
  101. p[0] ? "flex" : "none"
  102. };justify-content:space-between;align-items:center;">
  103. <span style="font-size:11px;color:#7ec7ff;">${
  104. p[0] ? p[0].seriesName : ""
  105. }</span>
  106. <span style="font-size:11px;color:#fff;">${p[0] ? p[0].data : ""}</span>
  107. </div>
  108. <div
  109. style="width:100%;height:100%;display:${
  110. p[1] ? "flex" : "none"
  111. };justify-content:space-between;align-items:center;">
  112. <span style="font-size:11px;color:#7ec7ff;">${
  113. p[1] ? p[1].seriesName : ""
  114. }</span>
  115. <span style="font-size:11px;color:#fff;">${p[1] ? p[1].data : ""}</span>
  116. </div>
  117. <div
  118. style="width:100%;height:100%;display:${
  119. p[1] ? "flex" : "none"
  120. };justify-content:space-between;align-items:center;">
  121. <span style="font-size:11px;color:#7ec7ff;">${
  122. p[2] ? p[2].seriesName : ""
  123. }</span>
  124. <span style="font-size:11px;color:#fff;">${p[2] ? p[2].data : ""}</span>
  125. </div>
  126. </div>
  127. </div>`;
  128. return dom;
  129. },
  130. },
  131. legend: {
  132. align: "left",
  133. right: "10%",
  134. top: "10%",
  135. type: "plain",
  136. textStyle: {
  137. color: "#7ec7ff",
  138. fontSize: 11,
  139. },
  140. // icon:'rect',
  141. itemGap: 25,
  142. itemWidth: 18,
  143. icon:
  144. "path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z",
  145. data: this.legend,
  146. },
  147. grid: {
  148. top: "15%",
  149. left: "10%",
  150. right: "10%",
  151. bottom: "15%",
  152. // containLabel: true
  153. },
  154. yAxis: [
  155. {
  156. boundaryGap: [0, "100%"],
  157. name: this.unit,
  158. splitLine: {
  159. show: true,
  160. lineStyle: {
  161. type: "dotted",
  162. color: "rgba(155, 155, 155, 0.5)",
  163. },
  164. },
  165. axisLine: {
  166. show: false,
  167. },
  168. axisLabel: {
  169. color: "#fff",
  170. fontSize: 11,
  171. },
  172. axisTick: { show: false },
  173. type: "value",
  174. },
  175. ],
  176. xAxis: [
  177. {
  178. // type: "time", // x轴为 时间轴
  179. interval: 0,
  180. splitLine: { show: false },
  181. axisLine: {
  182. lineStyle: { width: 0 },
  183. },
  184. axisLabel: {
  185. color: "#fff",
  186. fontSize: 11,
  187. rotate: 30,
  188. },
  189. axisTick: { show: false },
  190. boundaryGap: false,
  191. data: [],
  192. },
  193. ],
  194. title: {
  195. text: this.title,
  196. padding: [5, 230],
  197. textStyle: {
  198. fontWeight: "normal", //标题颜色
  199. color: "#4ADEFE",
  200. fontSize:15
  201. },
  202. },
  203. series: [
  204. {
  205. name: this.legend[0],
  206. type: "line",
  207. symbol: "circle", // 默认是空心圆(中间是白色的),改成实心圆
  208. showAllSymbol: true,
  209. symbolSize: 0,
  210. smooth: true,
  211. lineStyle: {
  212. normal: {
  213. width: 2,
  214. color: "rgba(255, 102, 102,1)", // 线条颜色
  215. },
  216. borderColor: "rgba(0,0,0,.4)",
  217. },
  218. itemStyle: {
  219. color: "rgba(255, 102, 102,1)",
  220. borderColor: "#646ace",
  221. borderWidth: 2,
  222. },
  223. tooltip: {
  224. show: true,
  225. },
  226. areaStyle: {
  227. //区域填充样式
  228. normal: {
  229. //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
  230. color: new echarts.graphic.LinearGradient(
  231. 0,
  232. 0,
  233. 0,
  234. 1,
  235. [
  236. {
  237. offset: 0,
  238. color: "rgba(255, 102, 102,.3)",
  239. },
  240. {
  241. offset: 1,
  242. color: "rgba(255, 102, 102, 0)",
  243. },
  244. ],
  245. false
  246. ),
  247. shadowColor: "rgba(255, 102, 102, 0.5)", //阴影颜色
  248. shadowBlur: 20, //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
  249. },
  250. },
  251. data: [],
  252. },
  253. {
  254. name: this.legend[1],
  255. type: "line",
  256. symbol: "circle", // 默认是空心圆(中间是白色的),改成实心圆
  257. showAllSymbol: true,
  258. symbolSize: 0,
  259. smooth: true,
  260. lineStyle: {
  261. normal: {
  262. width: 2,
  263. color: "rgba(0, 102, 153,1)", // 线条颜色
  264. },
  265. borderColor: "rgba(0,0,0,.4)",
  266. },
  267. itemStyle: {
  268. color: "rgba(0, 102, 153,1)",
  269. borderColor: "#3578e5",
  270. borderWidth: 2,
  271. },
  272. tooltip: {
  273. show: true,
  274. },
  275. areaStyle: {
  276. //区域填充样式
  277. normal: {
  278. //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
  279. color: new echarts.graphic.LinearGradient(
  280. 0,
  281. 0,
  282. 0,
  283. 1,
  284. [
  285. {
  286. offset: 0,
  287. color: "rgba(0, 102, 153,.3)",
  288. },
  289. {
  290. offset: 1,
  291. color: "rgba(0, 102, 153, 0)",
  292. },
  293. ],
  294. false
  295. ),
  296. shadowColor: "rgba(0, 102, 153, 0.5)", //阴影颜色
  297. shadowBlur: 20, //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
  298. },
  299. },
  300. data: [],
  301. },
  302. ],
  303. },
  304. };
  305. },
  306. computed: {
  307. ...mapState(["websocketIP"]),
  308. },
  309. methods: {
  310. idChange(id) {
  311. // console.log('this.legend',this.legend[0]);
  312. console.log("sep", id);
  313. // 数据清空
  314. this.xData = new Array(30).fill("-");
  315. this.y1Data = new Array(30).fill("-");
  316. this.y2Data = new Array(30).fill("-");
  317. // 关闭以前的websocket
  318. this.websocket.close();
  319. // 开启一个新的
  320. this.websocket = new WebSocket(
  321. `ws://${this.websocketIP}/hbase/ws/belt/${this.id}`
  322. );
  323. this.initWebSocket();
  324. },
  325. addData(data) {
  326. this.websocket;
  327. // 先扩展数组,然后删除多余元素
  328. console.log("data", data);
  329. if (this.count < 30) {
  330. for (let i = 0; i < data.length; i++) {
  331. this.y1Data[this.count] = data[i][this.type[0]];
  332. this.y2Data[this.count] = data[i][this.type[1]];
  333. this.xData[this.count] = data[i]["date"].split(" ")[1];
  334. }
  335. this.count++;
  336. } else {
  337. for (let i = 0; i < data.length; i++) {
  338. // 删除数组中的第一个项目
  339. this.y1Data.shift();
  340. this.y1Data.push(data[i][this.type[0]]);
  341. this.y2Data.shift();
  342. this.y2Data.push(data[i][this.type[1]]);
  343. this.xData.shift();
  344. this.xData.push(data[i]["date"].split(" ")[1]);
  345. }
  346. }
  347. this.myChart.setOption({
  348. xAxis: [{
  349. data: this.xData,
  350. }, ],
  351. series: [{
  352. name: this.legend[0],
  353. data: this.y1Data,
  354. },
  355. {
  356. name: this.legend[1],
  357. data: this.y2Data,
  358. }
  359. ],
  360. });
  361. // console.log("this.paiqidata", this.paiqidata);
  362. // console.log("this.chouqidata", this.chouqidata);
  363. // console.log("this.xData", this.xData);
  364. },
  365. initWebSocket() {
  366. // 连接错误
  367. this.websocket.onerror = () => {
  368. console.log(
  369. "WebSocket连接发生错误 状态码:" + this.websocket.readyState
  370. );
  371. };
  372. // 连接成功
  373. this.websocket.onopen = () => {
  374. console.log(
  375. "WebSocket连接成功 状态码:" + this.websocket.readyState
  376. );
  377. };
  378. // 收到消息的回调
  379. this.websocket.onmessage = (event) => {
  380. // console.log("onmessage", event);
  381. if (JSON.parse(event.data).length) {
  382. this.addData(JSON.parse(event.data));
  383. }
  384. };
  385. // 连接关闭的回调
  386. this.websocket.onclose = () => {
  387. console.log(
  388. "WebSocket连接关闭 状态码:" + this.websocket.readyState
  389. );
  390. };
  391. // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
  392. this.$once("hook:beforeDestroy", () => {
  393. this.websocket.close();
  394. });
  395. },
  396. },
  397. mounted() {
  398. // 先画图
  399. this.myChart = this.$echarts.init(this.$refs.testLine);
  400. this.myChart.setOption(this.option);
  401. this.websocket = new WebSocket(`ws://${this.websocketIP}/hbase/ws/belt/${this.id}`);
  402. this.initWebSocket();
  403. },
  404. };
  405. </script>
  406. <style scoped>
  407. .select-veido .el-select {
  408. width: 100px;
  409. margin-left: 10px;
  410. }
  411. .select-veido>>>.el-input--small .el-input__inner {
  412. background: none;
  413. }
  414. .select-veido>>>.el-input__inner {
  415. border: 0;
  416. }
  417. </style>