condition.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. <template>
  2. <view class="index-page">
  3. <navigation title="设备运行情况"></navigation>
  4. <view class="water-chart">
  5. <view class="water-item" @click="toDetail(1)">
  6. <canvas class="chart" canvas-id="boll" id="boll"></canvas>
  7. <view class="num">开机数量</view>
  8. </view>
  9. <view class="water-item" @click="toDetail(2)">
  10. <canvas class="chart1" canvas-id="boll1" id="boll1"></canvas>
  11. <view class="num">停机数量</view>
  12. </view>
  13. <view class="water-item" @click="toDetail(3)">
  14. <canvas class="chart2" canvas-id="boll2" id="boll2"></canvas>
  15. <view class="num">待机数量</view>
  16. </view>
  17. </view>
  18. <view class="chart-box">
  19. <qiun-data-charts type="line" :opts="opts" :chartData="chartData" />
  20. </view>
  21. <view class="chart-box">
  22. <qiun-data-charts type="mix" :opts="optsMix" :chartData="chartDataMix" />
  23. </view>
  24. </view>
  25. </template>
  26. <script>
  27. export default {
  28. data() {
  29. return {
  30. bollStep: null,
  31. bollTimeR: null,
  32. bollStep1: null,
  33. bollTimeR1: null,
  34. bollStep2: null,
  35. bollTimeR2: null,
  36. chartData: {},
  37. opts: {
  38. color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
  39. "#ea7ccc"
  40. ],
  41. padding: [15, 10, 0, 15],
  42. legend: {
  43. position: 'top'
  44. },
  45. xAxis: {
  46. disableGrid: true
  47. },
  48. yAxis: {
  49. gridType: "dash",
  50. dashLength: 2,
  51. data: [{
  52. tofix: 2,
  53. }]
  54. },
  55. extra: {
  56. line: {
  57. type: "curve",
  58. width: 2
  59. }
  60. }
  61. },
  62. chartDataMix: {},
  63. optsMix: {
  64. color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
  65. "#ea7ccc"
  66. ],
  67. padding: [15, 15, 0, 15],
  68. enableScroll: false,
  69. legend: {
  70. position: 'top'
  71. },
  72. xAxis: {
  73. disableGrid: true,
  74. title: ""
  75. },
  76. yAxis: {
  77. disabled: false,
  78. disableGrid: false,
  79. splitNumber: 5,
  80. gridType: "dash",
  81. dashLength: 4,
  82. gridColor: "#CCCCCC",
  83. padding: 10,
  84. showTitle: true,
  85. data: [{
  86. position: "left",
  87. title: "用电量"
  88. },
  89. {
  90. position: "right",
  91. min: 0,
  92. max: 200,
  93. title: "产能",
  94. textAlign: "left"
  95. },
  96. ]
  97. },
  98. extra: {
  99. mix: {
  100. column: {
  101. width: 20
  102. }
  103. }
  104. }
  105. }
  106. }
  107. },
  108. onLoad() {
  109. this.getServerData()
  110. this.getServerDataMix()
  111. },
  112. beforeDestroy() {
  113. // #ifdef H5
  114. cancelAnimationFrame(this.bollTimeR);
  115. cancelAnimationFrame(this.bollTimeR1);
  116. cancelAnimationFrame(this.bollTimeR2);
  117. // #endif
  118. // #ifdef APP-VUE || MP-WEIXIN
  119. clearInterval(this.bollTimeR);
  120. clearInterval(this.bollTimeR1);
  121. clearInterval(this.bollTimeR2);
  122. // #endif
  123. },
  124. onReady() {
  125. const query = uni.createSelectorQuery().in(this);
  126. query.select('.chart').boundingClientRect(data => {
  127. this.drawBollWave("boll", data);
  128. }).exec();
  129. query.select('.chart1').boundingClientRect(data => {
  130. this.drawBollWave1("boll1", data);
  131. }).exec();
  132. query.select('.chart2').boundingClientRect(data => {
  133. this.drawBollWave2("boll2", data);
  134. }).exec();
  135. },
  136. methods: {
  137. toDetail(type) {
  138. uni.navigateTo({
  139. url: '/subPackages/equipment/run?id=' + 1 + '&type=' + type
  140. })
  141. },
  142. // 折线图
  143. getServerData() {
  144. setTimeout(() => {
  145. let res = {
  146. categories: ["2018", "2019", "2020", "2021", "2022", "2023"],
  147. series: [{
  148. name: "稼动率",
  149. data: [35, 8, 25, 37, 4, 20]
  150. }, ]
  151. };
  152. this.chartData = JSON.parse(JSON.stringify(res));
  153. }, 500);
  154. },
  155. // 混合图
  156. getServerDataMix() {
  157. setTimeout(() => {
  158. let res = {
  159. categories: ["2018", "2019", "2020", "2021", "2022", "2023"],
  160. series: [{
  161. name: "产能",
  162. index: 1,
  163. type: "column",
  164. data: [40, 30, 55, 110, 24, 58]
  165. },
  166. {
  167. name: "用电量",
  168. type: "line",
  169. color: "#2fc25b",
  170. data: [120, 140, 105, 170, 95, 160]
  171. },
  172. ]
  173. };
  174. this.chartDataMix = JSON.parse(JSON.stringify(res));
  175. }, 500);
  176. },
  177. toFixedNumber(n = 2, val) { //去小数点后2位
  178. if (typeof val == "number") {
  179. return val.toFixed(n) * 1
  180. }
  181. },
  182. //绘制原型水球
  183. drawBollWave(ids, elem) {
  184. let ctx = uni.createCanvasContext(ids),
  185. w = elem.width,
  186. h = elem.height,
  187. grd = null, //渐变色grd
  188. angle = 0,
  189. x = 0,
  190. y = 0,
  191. y2 = 0,
  192. part = 0; //part声波初始位置
  193. let grid = {
  194. top: 5 * h / 100, //水球距离顶的 15%
  195. };
  196. let bollArg = {
  197. R: h / 2 - grid.top, //圆半径
  198. O: {
  199. x: w / 2,
  200. y: h / 2
  201. }, //圆心坐标 x, y
  202. A: 2, //振幅
  203. vs: 80, //声波运动速度 越大值 越慢
  204. lineWidth: 2,
  205. waveOpacity: 1, //水波的透明度
  206. waveHeight: 60, // 80百分之80%(占整个水球的百分比高度)
  207. angleStep: 5, //声波上圆点间隔的距离
  208. waveLen: 60, //波长
  209. waveStyle: {
  210. fillColor: {
  211. start: "#34EDA3",
  212. end: "#2fc25b"
  213. },
  214. strokeColor: "#212C67"
  215. }, //波浪颜色样式
  216. oStyle: {
  217. fillColor: "#f8f8f8",
  218. strokeColor: "#34EDA3"
  219. }, //圆的颜色样式
  220. textStyle: {
  221. fillColor: "#212C67",
  222. fontSize: 26
  223. },
  224. }
  225. let drawBoll = () => {
  226. ctx.clearRect(0, 0, w, h);
  227. ctx.save();
  228. ctx.beginPath();
  229. ctx.setLineWidth(bollArg.lineWidth);
  230. ctx.setStrokeStyle(bollArg.oStyle.strokeColor);
  231. ctx.setFillStyle(bollArg.oStyle.fillColor);
  232. ctx.arc(bollArg.O.x, bollArg.O.y, bollArg.R, 0, 2 * Math.PI);
  233. ctx.closePath();
  234. ctx.fill();
  235. ctx.stroke();
  236. ctx.clip();
  237. grd = ctx.createLinearGradient(0, 0, bollArg.O.y - bollArg.R, bollArg.O.y + bollArg.R);
  238. grd.addColorStop(0, bollArg.waveStyle.fillColor.start);
  239. grd.addColorStop(1, bollArg.waveStyle.fillColor.end);
  240. ctx.globalAlpha = bollArg.waveOpacity;
  241. ctx.beginPath();
  242. ctx.setStrokeStyle(bollArg.waveStyle.strokeColor);
  243. ctx.setFillStyle(grd);
  244. ctx.moveTo(bollArg.O.x - bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  245. for (angle = bollArg.O.x - bollArg.R; angle < bollArg.O.x + bollArg.R + bollArg.angleStep; angle +=
  246. bollArg.angleStep) {
  247. y = bollArg.A * Math.sin(this.bollStep / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  248. // y2 = bollArg.A * Math.cos(this.bollStep / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  249. x = angle;
  250. ctx.lineTo(x, (y + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  251. bollArg.waveHeight / 100));
  252. // ctx.lineTo(x, (y2 + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  253. // bollArg.waveHeight / 100));
  254. }
  255. ctx.lineTo(bollArg.O.x + bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  256. ctx.fill();
  257. ctx.restore();
  258. ctx.beginPath();
  259. ctx.setTextAlign("center");
  260. ctx.setTextBaseline("middle");
  261. ctx.setFillStyle(bollArg.textStyle.fillColor);
  262. ctx.setFontSize(bollArg.textStyle.fontSize);
  263. ctx.fillText(this.toFixedNumber(2, bollArg.waveHeight * 0.01 * part) + "%", bollArg.O.x, bollArg.O
  264. .y);
  265. ctx.fill();
  266. ctx.draw();
  267. part++;
  268. if (part >= 100) {
  269. part = 100;
  270. }
  271. // #ifdef H5
  272. this.bollStep++;
  273. if (this.bollStep > 2012) {
  274. this.bollStep = 0;
  275. }
  276. this.bollTimeR = requestAnimationFrame(drawBoll);
  277. // #endif
  278. }
  279. // #ifdef H5
  280. drawBoll();
  281. // #endif
  282. // #ifdef APP-VUE || MP-WEIXIN
  283. this.bollTimeR = setInterval(() => {
  284. drawBoll();
  285. this.bollStep++;
  286. if (this.bollStep > 2021) {
  287. this.bollStep = 0;
  288. }
  289. }, 1000 / 65);
  290. // #endif
  291. },
  292. drawBollWave1(ids, elem) {
  293. let ctx = uni.createCanvasContext(ids),
  294. w = elem.width,
  295. h = elem.height,
  296. grd = null, //渐变色grd
  297. angle = 0,
  298. x = 0,
  299. y = 0,
  300. y2 = 0,
  301. part = 0; //part声波初始位置
  302. let grid = {
  303. top: 5 * h / 100, //水球距离顶的 15%
  304. };
  305. let bollArg = {
  306. R: h / 2 - grid.top, //圆半径
  307. O: {
  308. x: w / 2,
  309. y: h / 2
  310. }, //圆心坐标 x, y
  311. A: 2, //振幅
  312. vs: 80, //声波运动速度 越大值 越慢
  313. lineWidth: 2,
  314. waveOpacity: 1, //水波的透明度
  315. waveHeight: 80, // 80百分之80%(占整个水球的百分比高度)
  316. angleStep: 5, //声波上圆点间隔的距离
  317. waveLen: 80, //波长
  318. waveStyle: {
  319. fillColor: {
  320. start: "#F0737E",
  321. end: "#FE5455"
  322. },
  323. strokeColor: "#212C67"
  324. }, //波浪颜色样式
  325. oStyle: {
  326. fillColor: "#f8f8f8",
  327. strokeColor: "#F0737E"
  328. }, //圆的颜色样式
  329. textStyle: {
  330. fillColor: "#212C67",
  331. fontSize: 26
  332. },
  333. }
  334. let drawBoll1 = () => {
  335. ctx.clearRect(0, 0, w, h);
  336. ctx.save();
  337. ctx.beginPath();
  338. ctx.setLineWidth(bollArg.lineWidth);
  339. ctx.setStrokeStyle(bollArg.oStyle.strokeColor);
  340. ctx.setFillStyle(bollArg.oStyle.fillColor);
  341. ctx.arc(bollArg.O.x, bollArg.O.y, bollArg.R, 0, 2 * Math.PI);
  342. ctx.closePath();
  343. ctx.fill();
  344. ctx.stroke();
  345. ctx.clip();
  346. grd = ctx.createLinearGradient(0, 0, bollArg.O.y - bollArg.R, bollArg.O.y + bollArg.R);
  347. grd.addColorStop(0, bollArg.waveStyle.fillColor.start);
  348. grd.addColorStop(1, bollArg.waveStyle.fillColor.end);
  349. ctx.globalAlpha = bollArg.waveOpacity;
  350. ctx.beginPath();
  351. ctx.setStrokeStyle(bollArg.waveStyle.strokeColor);
  352. ctx.setFillStyle(grd);
  353. ctx.moveTo(bollArg.O.x - bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  354. for (angle = bollArg.O.x - bollArg.R; angle < bollArg.O.x + bollArg.R + bollArg.angleStep; angle +=
  355. bollArg.angleStep) {
  356. y = bollArg.A * Math.sin(this.bollStep1 / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  357. // y2 = bollArg.A * Math.cos(this.bollStep1 / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  358. x = angle;
  359. ctx.lineTo(x, (y + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  360. bollArg.waveHeight / 100));
  361. // ctx.lineTo(x, (y2 + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  362. // bollArg.waveHeight / 100));
  363. }
  364. ctx.lineTo(bollArg.O.x + bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  365. ctx.fill();
  366. ctx.restore();
  367. ctx.beginPath();
  368. ctx.setTextAlign("center");
  369. ctx.setTextBaseline("middle");
  370. ctx.setFillStyle(bollArg.textStyle.fillColor);
  371. ctx.setFontSize(bollArg.textStyle.fontSize);
  372. ctx.fillText(this.toFixedNumber(2, bollArg.waveHeight * 0.01 * part) + "%", bollArg.O.x, bollArg.O
  373. .y);
  374. ctx.fill();
  375. ctx.draw();
  376. part++;
  377. if (part >= 100) {
  378. part = 100;
  379. }
  380. // #ifdef H5
  381. this.bollStep1++;
  382. if (this.bollStep1 > 2012) {
  383. this.bollStep1 = 0;
  384. }
  385. this.bollTimeR1 = requestAnimationFrame(drawBoll1);
  386. // #endif
  387. }
  388. // #ifdef H5
  389. drawBoll1();
  390. // #endif
  391. // #ifdef APP-VUE || MP-WEIXIN
  392. this.bollTimeR1 = setInterval(() => {
  393. drawBoll1();
  394. this.bollStep1++;
  395. if (this.bollStep1 > 2021) {
  396. this.bollStep1 = 0;
  397. }
  398. }, 1000 / 65);
  399. // #endif
  400. },
  401. drawBollWave2(ids, elem) {
  402. let ctx = uni.createCanvasContext(ids),
  403. w = elem.width,
  404. h = elem.height,
  405. grd = null, //渐变色grd
  406. angle = 0,
  407. x = 0,
  408. y = 0,
  409. y2 = 0,
  410. part = 0; //part声波初始位置
  411. let grid = {
  412. top: 5 * h / 100, //水球距离顶的 15%
  413. };
  414. let bollArg = {
  415. R: h / 2 - grid.top, //圆半径
  416. O: {
  417. x: w / 2,
  418. y: h / 2
  419. }, //圆心坐标 x, y
  420. A: 2, //振幅
  421. vs: 80, //声波运动速度 越大值 越慢
  422. lineWidth: 2,
  423. waveOpacity: 1, //水波的透明度
  424. waveHeight: 10, // 80百分之80%(占整个水球的百分比高度)
  425. angleStep: 5, //声波上圆点间隔的距离
  426. waveLen: 10, //波长
  427. waveStyle: {
  428. fillColor: {
  429. start: "#FFCB31",
  430. end: "#E9A90E"
  431. },
  432. strokeColor: "#212C67"
  433. }, //波浪颜色样式
  434. oStyle: {
  435. fillColor: "#f8f8f8",
  436. strokeColor: "#FFCB31"
  437. }, //圆的颜色样式
  438. textStyle: {
  439. fillColor: "#212C67",
  440. fontSize: 26
  441. },
  442. }
  443. let drawBoll2 = () => {
  444. ctx.clearRect(0, 0, w, h);
  445. ctx.save();
  446. ctx.beginPath();
  447. ctx.setLineWidth(bollArg.lineWidth);
  448. ctx.setStrokeStyle(bollArg.oStyle.strokeColor);
  449. ctx.setFillStyle(bollArg.oStyle.fillColor);
  450. ctx.arc(bollArg.O.x, bollArg.O.y, bollArg.R, 0, 2 * Math.PI);
  451. ctx.closePath();
  452. ctx.fill();
  453. ctx.stroke();
  454. ctx.clip();
  455. grd = ctx.createLinearGradient(0, 0, bollArg.O.y - bollArg.R, bollArg.O.y + bollArg.R);
  456. grd.addColorStop(0, bollArg.waveStyle.fillColor.start);
  457. grd.addColorStop(1, bollArg.waveStyle.fillColor.end);
  458. ctx.globalAlpha = bollArg.waveOpacity;
  459. ctx.beginPath();
  460. ctx.setStrokeStyle(bollArg.waveStyle.strokeColor);
  461. ctx.setFillStyle(grd);
  462. ctx.moveTo(bollArg.O.x - bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  463. for (angle = bollArg.O.x - bollArg.R; angle < bollArg.O.x + bollArg.R + bollArg.angleStep; angle +=
  464. bollArg.angleStep) {
  465. y = bollArg.A * Math.sin(this.bollStep2 / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  466. // y2 = bollArg.A * Math.cos(this.bollStep2 / bollArg.vs + angle / bollArg.waveLen * Math.PI * 2);
  467. x = angle;
  468. ctx.lineTo(x, (y + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  469. bollArg.waveHeight / 100));
  470. // ctx.lineTo(x, (y2 + bollArg.R * 2 + bollArg.A + grid.top) - part * 0.01 * (bollArg.R * 2 *
  471. // bollArg.waveHeight / 100));
  472. }
  473. ctx.lineTo(bollArg.O.x + bollArg.R, bollArg.O.y + bollArg.R + bollArg.A);
  474. ctx.fill();
  475. ctx.restore();
  476. ctx.beginPath();
  477. ctx.setTextAlign("center");
  478. ctx.setTextBaseline("middle");
  479. ctx.setFillStyle(bollArg.textStyle.fillColor);
  480. ctx.setFontSize(bollArg.textStyle.fontSize);
  481. ctx.fillText(this.toFixedNumber(2, bollArg.waveHeight * 0.01 * part) + "%", bollArg.O.x, bollArg.O
  482. .y);
  483. ctx.fill();
  484. ctx.draw();
  485. part++;
  486. if (part >= 100) {
  487. part = 100;
  488. }
  489. // #ifdef H5
  490. this.bollStep2++;
  491. if (this.bollStep2 > 2012) {
  492. this.bollStep2 = 0;
  493. }
  494. this.bollTimeR2 = requestAnimationFrame(drawBoll2);
  495. // #endif
  496. }
  497. // #ifdef H5
  498. drawBoll2();
  499. // #endif
  500. // #ifdef APP-VUE || MP-WEIXIN
  501. this.bollTimeR2 = setInterval(() => {
  502. drawBoll2();
  503. this.bollStep2++;
  504. if (this.bollStep2 > 2021) {
  505. this.bollStep2 = 0;
  506. }
  507. }, 1000 / 65);
  508. // #endif
  509. },
  510. }
  511. }
  512. </script>
  513. <style lang="scss" scoped>
  514. .index-page {
  515. .water-chart {
  516. background-color: #fff;
  517. margin: 24rpx;
  518. padding: 20rpx;
  519. border-radius: 12rpx;
  520. display: flex;
  521. .water-item {
  522. width: 33%;
  523. margin-bottom: 20rpx;
  524. .chart {
  525. width: 100%;
  526. height: 220rpx;
  527. }
  528. .chart1 {
  529. width: 100%;
  530. height: 220rpx;
  531. }
  532. .chart2 {
  533. width: 100%;
  534. height: 220rpx;
  535. }
  536. .num {
  537. text-align: center;
  538. margin-top: 16rpx;
  539. }
  540. }
  541. }
  542. .chart-box {
  543. background-color: #fff;
  544. margin: 24rpx;
  545. padding: 20rpx;
  546. border-radius: 12rpx;
  547. }
  548. }
  549. </style>