3DDrawingChart.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <template>
  2. <div>
  3. <!-- 配色方案选择和图表类型切换 -->
  4. <div style="display: flex; align-items: center; padding-top: 20px">
  5. <div style="margin-right: 20px; display: flex; align-items: center">
  6. <el-select
  7. size="small"
  8. v-model="color1"
  9. @change="updateChartColor"
  10. placeholder="选择配色方案"
  11. style="width: 200px"
  12. >
  13. <el-option
  14. v-for="(scheme, index) in colorSchemes"
  15. :key="index"
  16. :label="scheme.label"
  17. :value="scheme.colors"
  18. :style="getOptionStyle(scheme.colors)"
  19. ></el-option>
  20. </el-select>
  21. </div>
  22. </div>
  23. <!-- 点大小控制 -->
  24. <div style="display: flex; align-items: center">
  25. <el-slider
  26. v-model="pointSize"
  27. :min="1"
  28. :max="15"
  29. :step="1"
  30. label="点的大小"
  31. show-stops
  32. style="width: 150px"
  33. @change="updateChartColor"
  34. ></el-slider>
  35. </div>
  36. <!-- 图表展示区域 -->
  37. <div style="height: 600px">
  38. <div
  39. :id="`plotly-3d-chart-` + index"
  40. style="width: 100%; height: 600px"
  41. ></div>
  42. <div
  43. v-loading="loading"
  44. :id="`plotly-3d-chart-` + index"
  45. ref="plotlyChart"
  46. style="height: 600px"
  47. >
  48. <el-empty v-if="isError" description="请求失败"></el-empty>
  49. </div>
  50. </div>
  51. </div>
  52. </template>
  53. <script>
  54. import Plotly from "plotly.js-dist";
  55. import axios from "axios";
  56. import { myMixin } from "@/mixins/chartRequestMixin";
  57. import { colorSchemes } from "@/views/overview/js/colors";
  58. export default {
  59. props: {
  60. fileAddr: {
  61. default: "",
  62. type: String,
  63. },
  64. index: {
  65. default: "",
  66. type: String,
  67. },
  68. },
  69. data() {
  70. return {
  71. color1: [
  72. "#DBEEBC",
  73. "#A8D7BE",
  74. "#8ECAC1",
  75. "#77BDC2",
  76. "#64ADC2",
  77. "#559ABE",
  78. "#4884B7",
  79. "#406DAB",
  80. "#3856A0",
  81. "#314291",
  82. "#28357A",
  83. "#1A285E",
  84. "#FF7F50",
  85. "#FFD700",
  86. "#90EE90",
  87. ], // 默认颜色
  88. chartData: {},
  89. chartType: "scatter", // 当前图表类型(默认是散点图)
  90. colorSchemes: [...colorSchemes],
  91. pointSize: 2, // 默认点大小
  92. };
  93. },
  94. mixins: [myMixin],
  95. async mounted() {
  96. this.getData();
  97. },
  98. methods: {
  99. async getData() {
  100. if (this.fileAddr !== "") {
  101. try {
  102. this.loading = true;
  103. this.cancelToken = axios.CancelToken.source();
  104. const resultChartsData = await axios.get(this.fileAddr, {
  105. cancelToken: this.cancelToken.token,
  106. });
  107. if (typeof resultChartsData.data === "string") {
  108. let dataString = resultChartsData.data;
  109. dataString = dataString.trim(); // 去除前后空格
  110. dataString = dataString.replace(/Infinity/g, '"Infinity"'); // 替换 Infinity 为 "Infinity"
  111. try {
  112. const parsedData = JSON.parse(dataString);
  113. this.chartData = parsedData;
  114. } catch (error) {
  115. console.error("JSON 解析失败:", error);
  116. }
  117. } else {
  118. this.chartData = resultChartsData.data;
  119. }
  120. this.renderChart();
  121. this.isError = false;
  122. this.loading = false;
  123. } catch (error) {
  124. this.isError = true;
  125. this.loading = false;
  126. }
  127. }
  128. },
  129. // 更新配色方案
  130. updateChartColor() {
  131. this.renderChart(); // 当配色方案或点大小发生变化时重新渲染图表
  132. },
  133. // 切换图表类型
  134. setChartType(type) {
  135. this.chartType = type;
  136. this.renderChart(); // 切换图表类型时重新渲染图表
  137. },
  138. // 获取配色选项样式
  139. getOptionStyle(scheme) {
  140. return {
  141. background: `linear-gradient(to right, ${scheme.join(", ")})`,
  142. color: "#fff",
  143. height: "30px",
  144. lineHeight: "30px",
  145. borderRadius: "4px",
  146. };
  147. },
  148. renderChart() {
  149. const uniqueColors = [...new Set(this.chartData.data[0].color)];
  150. if (!this.color1) {
  151. this.color1 = colorSchemes[0].colors;
  152. }
  153. const traces = uniqueColors.map((color, idx) => {
  154. const colorData = this.chartData.data[0].color.map((c) =>
  155. c === color ? 1 : 0
  156. );
  157. const trace = {
  158. x: this.chartData.data[0].xData.filter((_, i) => colorData[i] === 1),
  159. y: this.chartData.data[0].yData.filter((_, i) => colorData[i] === 1),
  160. z: this.chartData.data[0].zData.filter((_, i) => colorData[i] === 1),
  161. mode: this.chartType === "scatter" ? "markers" : "lines", // 根据选择的图表类型来设置模式
  162. type: "scatter3d",
  163. marker: {
  164. size: this.pointSize, // 使用动态点大小
  165. color: this.color1[idx], // 使用配色方案
  166. colorscale: "YlGnBu",
  167. },
  168. name: ` ${color}`,
  169. legendgroup: `group-${idx}`,
  170. hovertemplate:
  171. `${this.chartData.xaixs}:` +
  172. ` %{x} <br> ` +
  173. `${this.chartData.yaixs}:` +
  174. "%{y} <br>" +
  175. `${this.chartData.zaixs}:` +
  176. "%{z} <br>",
  177. };
  178. return trace;
  179. });
  180. const layout = {
  181. title: this.chartData.data[0].title,
  182. scene: {
  183. xaxis: {
  184. title: this.chartData.xaixs,
  185. gridcolor: "rgb(255,255,255)",
  186. tickcolor: "rgb(255,255,255)",
  187. backgroundcolor: "#e5ecf6",
  188. showbackground: true,
  189. },
  190. yaxis: {
  191. title: this.chartData.yaixs,
  192. gridcolor: "rgb(255,255,255)",
  193. tickcolor: "rgb(255,255,255)",
  194. backgroundcolor: "#e5ecf6",
  195. showbackground: true,
  196. },
  197. zaxis: {
  198. title: this.chartData.zaixs,
  199. gridcolor: "rgb(255,255,255)",
  200. tickcolor: "rgb(255,255,255)",
  201. backgroundcolor: "#e5ecf6",
  202. showbackground: true,
  203. },
  204. // aspectratio: {
  205. // x: 1,
  206. // y: 3,
  207. // z: 1,
  208. // },
  209. plot_bgcolor: "#e5ecf6",
  210. gridcolor: "#fff",
  211. // camera: {
  212. // center: { x: 0, y: 0, z: 0 },
  213. // eye: { x: 0, y: 0, z: 2.5 },
  214. // up: { x: 0, y: 0, z: 1 },
  215. // },
  216. },
  217. margin: { t: 50, b: 50, l: 50, r: 50 },
  218. staticPlot: false,
  219. showlegend: true,
  220. legend: {
  221. marker: {
  222. size: 10, // 图例中点的大小
  223. },
  224. },
  225. };
  226. Plotly.newPlot(`plotly-3d-chart-` + this.index, traces, layout);
  227. },
  228. },
  229. };
  230. </script>
  231. <style scoped>
  232. /* 样式可以根据需求自定义 */
  233. #plotly-3d-chart {
  234. width: 100%;
  235. height: 500px;
  236. }
  237. ::v-deep canvas {
  238. /* height: 400px !important; */
  239. }
  240. </style>