WindRoseChart.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div>
  3. <div v-loading="loading" :id="`plotDiv-${inds}`" style="width: 100%; height: 550px">
  4. <el-empty v-if="isError" description="请求失败"></el-empty>
  5. </div>
  6. </div>
  7. </template>
  8. <script>
  9. import Plotly from "plotly.js-dist";
  10. import axios from "axios";
  11. import { myMixin } from "@/mixins/chartRequestMixin";
  12. export default {
  13. props: {
  14. fileAddr: {
  15. default: "",
  16. type: String,
  17. },
  18. inds: {
  19. type: [Number, String],
  20. default: 1,
  21. },
  22. },
  23. mixins: [myMixin],
  24. data() {
  25. return {
  26. // 数据结构
  27. chartData: {},
  28. };
  29. },
  30. watch: {
  31. chartData: {
  32. deep: true,
  33. handler(v) {
  34. if (v) {
  35. this.renderChart();
  36. }
  37. },
  38. },
  39. },
  40. mounted() {
  41. this.getData();
  42. },
  43. methods: {
  44. async getData() {
  45. if (this.fileAddr !== "") {
  46. try {
  47. this.loading = true
  48. this.cancelToken = axios.CancelToken.source();
  49. console.log(this.cancelToken)
  50. const resultChartsData = await axios.get(this.fileAddr, {
  51. cancelToken: this.cancelToken.token
  52. });
  53. console.log(resultChartsData)
  54. this.chartData = resultChartsData.data;
  55. this.renderChart();
  56. this.isError = false
  57. this.loading = false
  58. } catch (error) {
  59. this.isError = true
  60. this.loading = false
  61. }
  62. }
  63. },
  64. renderChart() {
  65. const { axes, data, analysisTypeCode } = this.chartData;
  66. // 从数据中提取 windSpeedRange 和动态生成 speedLabels 和 colorscale
  67. const windSpeedRanges = new Set();
  68. data.forEach((engine) => {
  69. engine.windRoseData.forEach((item) => {
  70. windSpeedRanges.add(item.windSpeedRange);
  71. });
  72. });
  73. const speedLabels = Array.from(windSpeedRanges).sort(); // 动态范围值
  74. const colors = [
  75. "#FBFDD4",
  76. "#C0E2BA",
  77. "#57A3BF",
  78. "#1A2971",
  79. "#FF6F61",
  80. "#FFC300",
  81. "#6A0572",
  82. ]; // 可扩展颜色列表
  83. const colorscale = {};
  84. speedLabels.forEach((label, index) => {
  85. colorscale[label] = colors[index % colors.length];
  86. });
  87. // 定义风向的 16 等分
  88. const windDirections = Array.from({ length: 16 }, (_, i) => i * 22.5);
  89. // 数据聚合
  90. const counts = {};
  91. speedLabels.forEach((speedLabel) => {
  92. counts[speedLabel] = Array(windDirections.length).fill(0);
  93. });
  94. data.forEach((engine) => {
  95. engine.windRoseData.forEach((item) => {
  96. const { windDirection, windSpeedRange } = item;
  97. const index = windDirections.findIndex(
  98. (dir, i) =>
  99. windDirection >= dir && windDirection < windDirections[i + 1]
  100. );
  101. if (index !== -1 && counts[windSpeedRange]) {
  102. counts[windSpeedRange][index] += item.frequency;
  103. }
  104. });
  105. });
  106. // 构建 traces
  107. const traces = speedLabels.map((speedLabel) => {
  108. const percentage = counts[speedLabel];
  109. return {
  110. r: percentage,
  111. theta: windDirections,
  112. name: speedLabel,
  113. type: "barpolar",
  114. marker: {
  115. color: colorscale[speedLabel],
  116. line: {
  117. color: "white",
  118. width: 1,
  119. },
  120. },
  121. };
  122. });
  123. // 图表布局
  124. const layout = {
  125. title: `${analysisTypeCode} - ${data[0]?.enginName} `,
  126. plot_bgcolor: "#e5ecf6",
  127. polar: {
  128. bgcolor: "#e5ecf6",
  129. radialaxis: {
  130. title: { text: axes.radial },
  131. gridcolor: "rgb(255,255,255)",
  132. showgrid: true,
  133. linecolor: "rgb(255,255,255)",
  134. },
  135. angularaxis: {
  136. title: { text: axes.angular },
  137. tickvals: windDirections,
  138. gridcolor: "rgb(255,255,255)",
  139. tickcolor: "rgb(255,255,255)",
  140. linecolor: "rgb(255,255,255)",
  141. },
  142. },
  143. showlegend: true,
  144. legend: { title: { text: axes.levelname } },
  145. };
  146. Plotly.newPlot(`plotDiv-${this.inds}`, traces, layout);
  147. },
  148. },
  149. };
  150. </script>
  151. <style scoped></style>