TemChart.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <template>
  2. <div
  3. class="temChart"
  4. :class="[screenType === 'hor' ? 'horiCompClass' : 'verCompClass ']"
  5. >
  6. <div class="temChartCont">
  7. <div
  8. class="subhead-title"
  9. v-show="screenType === 'ver'"
  10. >
  11. <span>实时温度</span>
  12. </div>
  13. <div
  14. id="tempChartBox"
  15. class="tempChartBox"
  16. ref="tempChartRef"
  17. ></div>
  18. </div>
  19. </div>
  20. </template>
  21. <script lang="ts">
  22. import {
  23. ref,
  24. defineComponent,
  25. reactive,
  26. toRefs,
  27. onMounted,
  28. nextTick,
  29. } from "vue";
  30. import { queryIndoorTempList } from "@/api";
  31. import { Chart, registerShape } from "@antv/g2";
  32. import moment from "moment";
  33. export default defineComponent({
  34. props: {
  35. screenType: {
  36. type: String,
  37. },
  38. },
  39. setup(props, contx) {
  40. //console.log("props", props, contx);
  41. const { screenType } = props;
  42. const allData = reactive({});
  43. const tempChartRef = ref();
  44. const cInitChart = (cdata, minTemp, maxTemp) => {
  45. registerShape("point", "breath-point", {
  46. draw(cfg, container) {
  47. const data = cfg.data;
  48. const point = { x: cfg.x, y: cfg.y };
  49. const group = container.addGroup();
  50. if (
  51. data.time === cdata[cdata.length - 1].time &&
  52. data.temp === cdata[cdata.length - 1].temp
  53. ) {
  54. const decorator1 = group.addShape("circle", {
  55. attrs: {
  56. x: point.x,
  57. y: point.y,
  58. r: 8,
  59. fill: "#F2E2CC",
  60. // opacity: 0.8,
  61. },
  62. });
  63. // decorator1.animate(
  64. // {
  65. // r: 20,
  66. // opacity: 0,
  67. // },
  68. // {
  69. // duration: 1800,
  70. // easing: "easeLinear",
  71. // repeat: true,
  72. // }
  73. // );
  74. group.addShape("circle", {
  75. attrs: {
  76. x: point.x,
  77. y: point.y,
  78. r: 4,
  79. fill: "#ffffff",
  80. filter: "blur(2px)",
  81. opacity: 0.5,
  82. },
  83. });
  84. // group.addShape("circle", {
  85. // attrs: {
  86. // x: point.x,
  87. // y: point.y,
  88. // r: 1.5,
  89. // fill: "#1890ff",
  90. // },
  91. // });
  92. }
  93. return group;
  94. },
  95. });
  96. var chartWidth =
  97. (tempChartRef.value && tempChartRef.value.offsetWidth) || 0;
  98. var chartHeight =
  99. (tempChartRef.value && tempChartRef.value.offsetHeight) || 0;
  100. // if (this.tempChart) {
  101. // this.tempChart.clear();
  102. // var chart = this.tempChart;
  103. // } else {
  104. var chart = new Chart({
  105. container: "tempChartBox",
  106. autoFit: true,
  107. // width: chartWidth,
  108. // height: chartHeight,
  109. padding: [70, 50, 46, 60],
  110. });
  111. // }
  112. chart.data(cdata);
  113. chart.scale("time", {
  114. //range: [0, 1],
  115. //tickCount: 2,
  116. //tickInterval
  117. // type: 'timeCat'
  118. });
  119. chart.scale("temp", {
  120. type: "linear",
  121. minTickInterval: 1,
  122. min: minTemp,
  123. max: maxTemp,
  124. //ticks:[22,23,24,25,26,27]
  125. });
  126. chart.axis("time", {
  127. line: {
  128. style: {
  129. lineWidth: 1, // 设置线的宽度
  130. stroke: "rgba(224,194,155,0.2)", // 设置线的颜色
  131. lineDash: [3, 3], // 设置虚线样式
  132. },
  133. },
  134. label: {
  135. style: {
  136. fill: "#E0C29B",
  137. fontSize: 12,
  138. },
  139. },
  140. tickLine: null,
  141. });
  142. chart.axis("temp", {
  143. tickLine: null,
  144. grid: {
  145. line: {
  146. style: {
  147. lineWidth: 1, // 设置线的宽度
  148. stroke: "rgba(224,194,155,0.2)", // 设置线的颜色
  149. lineDash: [3, 3], // 设置虚线样式
  150. },
  151. },
  152. },
  153. label: {
  154. style: {
  155. fill: "#E0C29B",
  156. fontSize: 12,
  157. },
  158. // formatter: function formatter(text) {
  159. // return text;
  160. // }
  161. },
  162. });
  163. chart.legend(false);
  164. chart
  165. .line()
  166. .animate({
  167. appear: {
  168. //animation: "fade-in", // 动画名称
  169. easing: "easeQuadIn", // 动画缓动效果
  170. delay: 100, // 动画延迟执行时间
  171. duration: 1500, // 动画执行时间
  172. },
  173. })
  174. .position("time*temp")
  175. .color("#F2E3CD")
  176. .shape("smooth")
  177. .tooltip(false)
  178. .style({
  179. lineWidth: 3,
  180. });
  181. chart
  182. .area()
  183. .animate({
  184. appear: {
  185. //animation: "fade-in", // 动画名称
  186. easing: "easeQuadIn", // 动画缓动效果
  187. delay: 100, // 动画延迟执行时间
  188. duration: 1500, // 动画执行时间
  189. },
  190. })
  191. .position("time*temp")
  192. .color(
  193. "l(90) 0:rgba(237,217,190,0.8) 0.6:rgb(149, 162, 194, 0.01)"
  194. )
  195. .tooltip(false)
  196. .shape("smooth");
  197. chart
  198. .point()
  199. .tooltip(false)
  200. .position("time*temp")
  201. .shape("breath-point");
  202. var lastpoint = cdata[cdata.length - 1];
  203. var nowtime = moment();
  204. var timestr = nowtime.format("YYYY.MM.DD");
  205. const tooltipHtml = `<div style='line-height:22px;color:#321D0A;background: linear-gradient(105.46deg, #F2E3CD 8.6%, #D9B991 62.71%);padding:16px 17px;border-radius:5px;white-space:nowrap;'>
  206. <div style='font-size:12px;font-weight:600;'><span style='margin-right:5px;line-height:17px;'>${timestr}</span>${lastpoint &&
  207. lastpoint.time}</div>
  208. <div style='font-size:16px;font-weight:600;margin-top:4px;'>室内温度:${lastpoint &&
  209. lastpoint.temp &&
  210. Number(lastpoint.temp).toFixed(1)}℃</div></div>`;
  211. chart.annotation().html({
  212. position: lastpoint,
  213. html: tooltipHtml,
  214. alignX: "right",
  215. alignY: "bottom",
  216. offsetX: 60,
  217. offsetY: -15,
  218. });
  219. chart.annotation().text({
  220. // position: ['min', 'max'], // 文本的起始位置,值为原始数据值,支持 callback
  221. position: function(xScale, yScale) {
  222. //console.log("position", xScale, yScale);
  223. return ["0%", "0%"];
  224. },
  225. content: "温度/℃", // 显示的文本内容
  226. style: {
  227. fill: "#E0C29B", // 文本颜色
  228. fontSize: "12", // 文本大小
  229. // fontWeight: 'bold' // 文本粗细
  230. // rotate: Math.PI / 4 // 文本旋转,以弧度为单位
  231. }, // 文本的图形样式属性
  232. offsetX: -40, // x 方向的偏移量
  233. offsetY: -46, // y 方向偏移量
  234. });
  235. chart.render();
  236. return chart;
  237. };
  238. onMounted(() => {
  239. queryIndoorTempList()
  240. .then((res) => {
  241. var cdata = res.data.data || [];
  242. var tempArr = [];
  243. cdata.forEach((element) => {
  244. var timestr = element.time || "";
  245. var hour = timestr.substr(8, 2);
  246. var minute = timestr.substr(10, 2);
  247. element.time = hour + ":" + minute;
  248. element.temp =
  249. element && element.temp
  250. ? Number(element.temp).toFixed(1)
  251. : element.temp;
  252. element.temp && tempArr.push(element.temp);
  253. });
  254. var minTemp = Math.floor(Math.min(...tempArr));
  255. var maxTemp = Math.ceil(Math.max(...tempArr));
  256. // debugger;
  257. nextTick(() => {
  258. cInitChart(cdata, minTemp, maxTemp);
  259. });
  260. })
  261. .catch((err) => {});
  262. });
  263. return { ...toRefs(allData), tempChartRef };
  264. },
  265. });
  266. </script>
  267. <style scoped lang="scss">
  268. .temChart {
  269. .temChartCont {
  270. width: 100%;
  271. height: 100%;
  272. box-sizing: border-box;
  273. font-size: 0;
  274. }
  275. .tempChartBox {
  276. width: 100%;
  277. height: 100%;
  278. box-sizing: border-box;
  279. // height: 330px;
  280. }
  281. }
  282. .horiCompClass {
  283. height: 100%;
  284. box-sizing: border-box;
  285. padding: 50px 20px 20px;
  286. }
  287. .verCompClass {
  288. // margin: 22px 0;
  289. //height: 410px;
  290. height: 31%;
  291. padding: 28px 0;
  292. box-sizing: border-box;
  293. .temChartCont {
  294. padding: 0 36px;
  295. background: rgba(149, 162, 194, 0.1);
  296. backdrop-filter: blur(40px);
  297. border-radius: 20px;
  298. }
  299. .tempChartBox {
  300. height: calc(100% - 60px);
  301. padding-top: 30px;
  302. box-sizing: border-box;
  303. }
  304. }
  305. </style>