warnZb.vue 12 KB

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