warn-zb.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <template>
  2. <view class="warn-zb">
  3. <view
  4. ref="coord"
  5. class="coords"
  6. :style="{ width: widthV, height: heightV }"
  7. >
  8. <view class="triangle-x"></view>
  9. <view class="triangle-y"></view>
  10. <view class="name-x">时间</view>
  11. <view class="name-y">温度(℃)</view>
  12. <view class="coord-dw">
  13. <view class="dw-item" :style="{ bottom: `${coordDw[0]}px` }">12</view>
  14. <view class="dw-item" :style="{ bottom: `${coordDw[1]}px` }">200</view>
  15. </view>
  16. <view class="coord-bj">
  17. <view
  18. class="bj-qfq"
  19. :style="{ width: widthCanvas == '302px' ? '100px' : '401px' }"
  20. >
  21. <view class="left-jt"></view>
  22. <view class="line"></view>
  23. <view class="right-jt"></view>
  24. <view class="text">缓慢氧化阶段</view>
  25. </view>
  26. <view
  27. class="bj-zrq"
  28. :style="{ width: widthCanvas == '302px' ? '50px' : '250px' }"
  29. >
  30. <view class="left-jt"></view>
  31. <view class="line"></view>
  32. <view class="right-jt"></view>
  33. <view class="text">加速氧化阶段</view>
  34. </view>
  35. <view
  36. class="bj-rsq"
  37. :style="{ width: widthCanvas == '302px' ? '100px' : '570px' }"
  38. >
  39. <view class="left-jt"></view>
  40. <view class="line"></view>
  41. <view class="text">剧烈氧化阶段</view>
  42. </view>
  43. </view>
  44. <view
  45. class="coord-area"
  46. :style="{
  47. width: 'calc(100% - 10px)',
  48. height: 'calc(100% - 10px)',
  49. overflow: 'hidden',
  50. }"
  51. >
  52. <canvas
  53. :id="`myCanvas${resetIndex}`"
  54. :style="{ width: widthCanvas, height: heightCanvas }"
  55. ></canvas>
  56. </view>
  57. </view>
  58. </view>
  59. </template>
  60. <script>
  61. import api from "@/api/api";
  62. export default {
  63. name: "warnZb",
  64. props: {
  65. widthV: {
  66. type: String,
  67. default: "",
  68. },
  69. heightV: {
  70. type: String,
  71. default: "",
  72. },
  73. coordDw: {
  74. type: Array,
  75. default: () => {
  76. return [];
  77. },
  78. },
  79. widthCanvas: {
  80. type: String,
  81. default: 0,
  82. },
  83. heightCanvas: {
  84. type: String,
  85. default: 0,
  86. },
  87. warnLevel: {
  88. type: String,
  89. default: "",
  90. },
  91. resetIndex: {
  92. type: Number,
  93. default: 0,
  94. },
  95. },
  96. data() {
  97. return {
  98. coord: null,
  99. lengY: 0,
  100. //与x,y轴相交最大值坐标
  101. maxY: 0,
  102. maxX: 0,
  103. };
  104. },
  105. watch: {
  106. resetIndex: {
  107. handler(newR, oldR) {
  108. this.getCanvas(newR);
  109. },
  110. immediate: true,
  111. },
  112. },
  113. mounted() {
  114. this.getAreas();
  115. },
  116. methods: {
  117. getAreas() {
  118. if (this.coord) {
  119. let width = this.coord.offsetWidth;
  120. let height = this.coord.offsetHeight;
  121. this.lengY = Math.ceil((height - 10) / 10);
  122. }
  123. },
  124. getCanvas(index) {
  125. let that = this;
  126. that.$nextTick(() => {
  127. // 获取canvas元素
  128. let canvas = document.getElementById(`myCanvas${index}`).childNodes[0];
  129. let ctx = canvas.getContext("2d");
  130. let x = 0;
  131. let step = that.widthCanvas == "302px" ? 0.01 : 0.05; // 设置每次递增的长度
  132. let y = that.widthCanvas == "302px" ? 194 : 325; // 初始y坐标
  133. // 设置线条样式
  134. ctx.strokeStyle = "#3df6ff"; // 红色线条
  135. ctx.lineWidth = 1; // 线宽为2
  136. // 初始化曲线数据
  137. let xValues = [];
  138. let yValues = [];
  139. for (let i = 0; i < 30000; i++) {
  140. x += step;
  141. if (that.widthCanvas == "302px") {
  142. y -= (step * Math.random() * i) / 12000; // 随机增加长度,使曲线更加平滑
  143. } else {
  144. y -= (step * Math.random() * i) / 30000; // 随机增加长度,使曲线更加平滑
  145. }
  146. xValues[i] = x;
  147. yValues[i] = y;
  148. }
  149. // 绘制递增曲线
  150. ctx.beginPath();
  151. ctx.moveTo(xValues[0], yValues[0]);
  152. for (var i = 1; i < xValues.length; i++) {
  153. ctx.lineTo(xValues[i], yValues[i]);
  154. if (that.warnLevel == "绿色预警") {
  155. ctx.fillStyle = "rgba(145, 230, 9)"; // 设置填充颜色
  156. if (that.widthCanvas == "302px" && i <= 10000) {
  157. ctx.fillRect(
  158. xValues[i],
  159. yValues[i],
  160. step,
  161. canvas.height - yValues[i]
  162. );
  163. } else if (i <= 8000) {
  164. ctx.fillRect(
  165. xValues[i],
  166. yValues[i],
  167. step,
  168. canvas.height - yValues[i]
  169. );
  170. }
  171. } else if (that.warnLevel == "黄色预警") {
  172. ctx.fillStyle = "rgba(255, 255, 53)"; // 设置填充颜色
  173. if (that.widthCanvas == "302px" && i <= 15000) {
  174. ctx.fillRect(
  175. xValues[i],
  176. yValues[i],
  177. step,
  178. canvas.height - yValues[i]
  179. );
  180. } else if (i <= 13000) {
  181. ctx.fillRect(
  182. xValues[i],
  183. yValues[i],
  184. step,
  185. canvas.height - yValues[i]
  186. );
  187. }
  188. } else if (that.warnLevel == "红色预警") {
  189. ctx.fillStyle = "rgba(255, 0, 0)"; // 设置填充颜色
  190. if (that.widthCanvas == "302px" && i > 15000) {
  191. ctx.fillRect(
  192. xValues[i],
  193. yValues[i],
  194. step,
  195. canvas.height - yValues[i]
  196. );
  197. } else if (i > 13000) {
  198. ctx.fillRect(
  199. xValues[i],
  200. yValues[i],
  201. step,
  202. canvas.height - yValues[i]
  203. );
  204. }
  205. }
  206. }
  207. ctx.stroke();
  208. ctx.beginPath();
  209. ctx.arc(
  210. xValues[that.widthCanvas == "302px" ? 10000 : 8000],
  211. yValues[that.widthCanvas == "302px" ? 10000 : 8000],
  212. 5,
  213. 0,
  214. 2 * Math.PI
  215. );
  216. ctx.fillStyle = "#ff6363";
  217. ctx.fill();
  218. //标记点2
  219. ctx.beginPath();
  220. ctx.arc(
  221. xValues[that.widthCanvas == "302px" ? 15000 : 13000],
  222. yValues[that.widthCanvas == "302px" ? 15000 : 13000],
  223. 5,
  224. 0,
  225. 2 * Math.PI
  226. );
  227. ctx.fillStyle = "#ff6363";
  228. ctx.fill();
  229. // 设置线条样式(颜色、宽度等)
  230. ctx.strokeStyle = "rgba(14, 180, 252,.6)";
  231. ctx.lineWidth = 1;
  232. ctx.lineCap = "round";
  233. // 定义虚线模式:[线段长度, 间隔长度]
  234. ctx.setLineDash([5, 5]);
  235. //绘制标记点1线条-x
  236. ctx.beginPath();
  237. ctx.moveTo(0, yValues[that.widthCanvas == "302px" ? 10000 : 8000]); // 开始绘制的点
  238. ctx.lineTo(
  239. xValues[that.widthCanvas == "302px" ? 10000 : 8000],
  240. yValues[that.widthCanvas == "302px" ? 10000 : 8000]
  241. ); // 结束绘制的点
  242. ctx.stroke(); // 进行绘制
  243. //绘制标记点1线条-y
  244. ctx.beginPath();
  245. ctx.moveTo(
  246. xValues[that.widthCanvas == "302px" ? 10000 : 8000],
  247. yValues[that.widthCanvas == "302px" ? 10000 : 8000]
  248. ); // 开始绘制的点
  249. ctx.lineTo(
  250. xValues[that.widthCanvas == "302px" ? 10000 : 8000],
  251. canvas.height
  252. ); // 结束绘制的点
  253. ctx.stroke(); // 进行绘制
  254. //绘制标记点2线条-x
  255. ctx.beginPath();
  256. ctx.moveTo(0, yValues[that.widthCanvas == "302px" ? 15000 : 13000]); // 开始绘制的点
  257. ctx.lineTo(
  258. xValues[that.widthCanvas == "302px" ? 15000 : 13000],
  259. yValues[that.widthCanvas == "302px" ? 15000 : 13000]
  260. ); // 结束绘制的点
  261. ctx.stroke(); // 进行绘制
  262. //绘制标记点2线条-y
  263. ctx.beginPath();
  264. ctx.moveTo(
  265. xValues[that.widthCanvas == "302px" ? 15000 : 13000],
  266. yValues[that.widthCanvas == "302px" ? 15000 : 13000]
  267. ); // 开始绘制的点
  268. ctx.lineTo(
  269. xValues[that.widthCanvas == "302px" ? 15000 : 13000],
  270. canvas.height
  271. ); // 结束绘制的点
  272. ctx.stroke(); // 进行绘制
  273. });
  274. },
  275. },
  276. computed: {},
  277. };
  278. </script>
  279. <style lang="scss" scoped>
  280. .warn-zb {
  281. position: relative;
  282. height: 100%;
  283. .coords {
  284. position: absolute;
  285. left: 50%;
  286. top: 50%;
  287. border-left: 1px solid #0eb4fc;
  288. border-bottom: 1px solid #0eb4fc;
  289. transform: translate(-50%, -55%);
  290. .triangle-x {
  291. position: absolute;
  292. left: -4px;
  293. top: -10px;
  294. width: 0px;
  295. height: 0px;
  296. border-top: 3px solid transparent;
  297. border-left: 4px solid transparent;
  298. border-right: 3px solid transparent;
  299. border-bottom: 8px solid #0eb4fc;
  300. }
  301. .triangle-y {
  302. position: absolute;
  303. right: -10px;
  304. bottom: -4px;
  305. width: 0px;
  306. height: 0px;
  307. border-top: 4px solid transparent;
  308. border-left: 8px solid #0eb4fc;
  309. border-right: 3px solid transparent;
  310. border-bottom: 3px solid transparent;
  311. }
  312. .name-x {
  313. position: absolute;
  314. right: 0px;
  315. bottom: -20px;
  316. color: #b3b8cc;
  317. font-size: 12px;
  318. }
  319. .name-y {
  320. width: 20px;
  321. position: absolute;
  322. left: -24px;
  323. top: 0px;
  324. color: #b3b8cc;
  325. font-size: 12px;
  326. text-align: center;
  327. }
  328. .coord-dw {
  329. position: absolute;
  330. left: -32px;
  331. top: 0;
  332. width: 30px;
  333. height: 100%;
  334. .dw-item {
  335. position: absolute;
  336. left: 50%;
  337. transform: translate(-50%, 0);
  338. color: #b3b8cc;
  339. font-size: 12px;
  340. }
  341. }
  342. .coord-bj {
  343. display: flex;
  344. position: absolute;
  345. left: -1px;
  346. bottom: -31px;
  347. width: 100%;
  348. height: 30px;
  349. border-left: 1px solid #0eb4fc;
  350. .left-jt {
  351. position: absolute;
  352. left: -1px;
  353. top: 23px;
  354. width: 0px;
  355. height: 0px;
  356. border-top: 3px solid transparent;
  357. border-right: 8px solid #0eb4fc;
  358. border-left: 3px solid transparent;
  359. border-bottom: 3px solid transparent;
  360. }
  361. .right-jt {
  362. position: absolute;
  363. right: -1px;
  364. top: 23px;
  365. width: 0px;
  366. height: 0px;
  367. border-top: 3px solid transparent;
  368. border-left: 8px solid #0eb4fc;
  369. border-right: 3px solid transparent;
  370. border-bottom: 3px solid transparent;
  371. }
  372. .text {
  373. width: 100%;
  374. position: absolute;
  375. left: 50%;
  376. top: 50%;
  377. transform: translate(-50%, -55%);
  378. font-size: 10px;
  379. color: #db9753;
  380. text-align: center;
  381. }
  382. .line {
  383. width: calc(100% - 20px);
  384. height: 1px;
  385. position: absolute;
  386. left: 10px;
  387. top: 26px;
  388. background-color: #0eb4fc;
  389. }
  390. .bj-qfq {
  391. flex-shrink: 0;
  392. position: relative;
  393. // width: 401px;
  394. height: 100%;
  395. border-right: 1px dashed #0eb4fc;
  396. }
  397. .bj-zrq {
  398. flex-shrink: 0;
  399. position: relative;
  400. // width: 699px;
  401. height: 100%;
  402. border-right: 1px dashed #0eb4fc;
  403. }
  404. .bj-rsq {
  405. flex-shrink: 0;
  406. position: relative;
  407. // width: 415px;
  408. height: 100%;
  409. }
  410. }
  411. .coord-area {
  412. position: absolute;
  413. left: 0;
  414. top: 10px;
  415. }
  416. }
  417. }
  418. </style>