widgetPieNightingaleRose.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <template>
  2. <div :style="styleObj">
  3. <v-chart ref="myVChart" :options="options" autoresize/>
  4. </div>
  5. </template>
  6. <script>
  7. import {
  8. originWidgetLinkageLogic,
  9. targetWidgetLinkageLogic,
  10. } from "@/views/bigscreenDesigner/designer/linkageLogic";
  11. export default {
  12. name: "WidgetPieNightingaleRoseArea", //南丁格尔玫瑰图面积模式 参考:https://echarts.apache.org/examples/zh/editor.html?c=pie-roseType-simple
  13. components: {},
  14. props: {
  15. value: Object,
  16. ispreview: Boolean,
  17. },
  18. data() {
  19. return {
  20. options: {
  21. legend: {
  22. top: "bottom",
  23. },
  24. toolbox: {
  25. show: true,
  26. feature: {
  27. mark: {show: true},
  28. },
  29. },
  30. series: [
  31. {
  32. //name: "面积模式",
  33. type: "pie",
  34. radius: ["10%", "50%"],
  35. center: ["50%", "50%"],
  36. roseType: "area",
  37. itemStyle: {
  38. borderRadius: 8,
  39. },
  40. data: [],
  41. },
  42. ],
  43. },
  44. optionsStyle: {}, // 样式
  45. optionsData: {}, // 数据
  46. optionsCollapse: {}, // 图标属性
  47. optionsSetup: {},
  48. flagInter: null,
  49. };
  50. },
  51. computed: {
  52. styleObj() {
  53. return {
  54. position: this.ispreview ? "absolute" : "static",
  55. width: this.optionsStyle.width + "px",
  56. height: this.optionsStyle.height + "px",
  57. left: this.optionsStyle.left + "px",
  58. top: this.optionsStyle.top + "px",
  59. background: this.optionsSetup.background,
  60. };
  61. },
  62. allComponentLinkage() {
  63. return this.$store.state.designer.allComponentLinkage;
  64. },
  65. },
  66. watch: {
  67. value: {
  68. handler(val) {
  69. this.optionsStyle = val.position;
  70. this.optionsData = val.data;
  71. this.optionsCollapse = val.setup;
  72. this.optionsSetup = val.setup;
  73. this.editorOptions();
  74. },
  75. deep: true,
  76. },
  77. },
  78. mounted() {
  79. this.optionsStyle = this.value.position;
  80. this.optionsData = this.value.data;
  81. this.optionsCollapse = this.value.setup;
  82. this.optionsSetup = this.value.setup;
  83. this.editorOptions();
  84. targetWidgetLinkageLogic(this); // 联动-目标组件逻辑
  85. originWidgetLinkageLogic(this); // 联动-源组件逻辑
  86. },
  87. methods: {
  88. // 修改图标options属性
  89. editorOptions() {
  90. this.setOptionsTitle();
  91. this.setOptionsPie();
  92. this.setOptionsValue();
  93. this.setOptionsTooltip();
  94. this.setOptionsLegend();
  95. this.setOptionsColor();
  96. this.setOptionsData();
  97. },
  98. // 标题修改
  99. setOptionsTitle() {
  100. const optionsSetup = this.optionsSetup;
  101. const title = {
  102. text: optionsSetup.text,
  103. show: optionsSetup.isShowTitle,
  104. left: optionsSetup.titleLeft,
  105. top: optionsSetup.titleTop + "%",
  106. itemGap: optionsSetup.titleItemGap,
  107. textStyle: {
  108. color: optionsSetup.textColor,
  109. fontSize: optionsSetup.textFontSize,
  110. fontWeight: optionsSetup.textFontWeight,
  111. fontStyle: optionsSetup.textFontStyle,
  112. fontFamily: optionsSetup.textFontFamily,
  113. },
  114. subtext: optionsSetup.subtext,
  115. subtextStyle: {
  116. color: optionsSetup.subtextColor,
  117. fontWeight: optionsSetup.subtextFontWeight,
  118. fontSize: optionsSetup.subtextFontSize,
  119. fontStyle: optionsSetup.subtextFontStyle,
  120. fontFamily: optionsSetup.subtextFontFamily
  121. },
  122. };
  123. this.options.title = title;
  124. },
  125. // 饼图设置
  126. setOptionsPie() {
  127. const optionsSetup = this.optionsSetup;
  128. const series = {
  129. type: "pie",
  130. center: ["50%", "50%"],
  131. left: optionsSetup.left,
  132. top: optionsSetup.top,
  133. right: optionsSetup.right,
  134. bottom: optionsSetup.bottom,
  135. // 饼图模式 面积模式"area" 半径模式"radius"//name: "面积模式",
  136. roseType: optionsSetup.nightingaleRoseType,
  137. radius: [optionsSetup.innerNumber + "%", optionsSetup.outerNumber + "%"],
  138. clockwise: optionsSetup.clockwise,
  139. startAngle: optionsSetup.startAngle,
  140. minAngle: optionsSetup.minAngle,
  141. minShowLabelAngle: optionsSetup.minShowLabelAngle,
  142. percentPrecision: optionsSetup.percentPrecision,
  143. // echarts v5.0.0开始支持
  144. /* itemStyle: {
  145. borderRadius: [optionsSetup.borderRadius + "%", optionsSetup.borderRadius + "%"],
  146. },*/
  147. // 高亮的扇区
  148. emphasis: {
  149. label: {
  150. show: optionsSetup.isShowEmphasisLabel,
  151. color: optionsSetup.emphasisLabelFontColor == '' ? null : optionsSetup.EmphasisLabelFontColor,
  152. fontSize: optionsSetup.emphasisLabelFontSize,
  153. fontWeight: optionsSetup.emphasisLabelFontWeight,
  154. fontStyle: optionsSetup.emphasisLabelFontStyle,
  155. fontFamily: optionsSetup.emphasisLabelFontFamily,
  156. },
  157. // 视觉引导线
  158. labelLine: {
  159. show: false,
  160. },
  161. // 色块描边
  162. itemStyle: {
  163. borderColor: optionsSetup.borderColor == '' ? null : optionsSetup.borderColor,
  164. borderWidth: optionsSetup.borderWidth,
  165. borderType: optionsSetup.borderType,
  166. shadowBlur: optionsSetup.shadowBlur,
  167. shadowColor: optionsSetup.shadowColor,
  168. },
  169. },
  170. };
  171. this.options.series[0] = series;
  172. },
  173. // 数值设定
  174. setOptionsValue() {
  175. const optionsSetup = this.optionsSetup;
  176. const numberValue = optionsSetup.numberValue ? "\n{c}" : "";
  177. const percentage = optionsSetup.percentage ? "\n({d}%)" : "";
  178. const label = {
  179. show: optionsSetup.isShow,
  180. position: optionsSetup.position,
  181. rotate: optionsSetup.rotate,
  182. formatter: `{b}${numberValue}${percentage}`,
  183. padding: optionsSetup.padding,
  184. fontSize: optionsSetup.fontSize,
  185. color: optionsSetup.fontColor == '' ? null : optionsSetup.fontColor,
  186. fontWeight: optionsSetup.fontWeight,
  187. fontStyle: optionsSetup.fontStyle,
  188. fontFamily: optionsSetup.fontFamily,
  189. };
  190. // 引导线
  191. const labelLine = {
  192. show: optionsSetup.isShowLabelLine,
  193. length: optionsSetup.labelLineLength,
  194. length2: optionsSetup.labelLineLength2,
  195. smooth: optionsSetup.labelLineSmooth,
  196. lineStyle: {
  197. color: optionsSetup.lineStyleColor == '' ? null : optionsSetup.lineStyleColor,
  198. width: optionsSetup.lineStyleWidth,
  199. type: optionsSetup.lineStyleType,
  200. }
  201. }
  202. this.options.series[0].label = label;
  203. this.options.series[0].labelLine = labelLine;
  204. },
  205. // tooltip 设置
  206. setOptionsTooltip() {
  207. const optionsSetup = this.optionsSetup;
  208. const tooltip = {
  209. trigger: "item",
  210. show: optionsSetup.isShowTooltip,
  211. textStyle: {
  212. color: optionsSetup.tooltipColor,
  213. fontSize: optionsSetup.tooltipFontSize,
  214. fontWeight: optionsSetup.tooltipFontWeight,
  215. fontStyle: optionsSetup.tooltipFontStyle,
  216. fontFamily: optionsSetup.tooltipFontFamily,
  217. },
  218. };
  219. this.options.tooltip = tooltip;
  220. },
  221. // 图例操作 legend
  222. setOptionsLegend() {
  223. const optionsSetup = this.optionsSetup;
  224. const legend = {
  225. show: optionsSetup.isShowLegend,
  226. left: optionsSetup.lateralPosition,
  227. //right: optionsSetup.lateralPosition,
  228. top: optionsSetup.longitudinalPosition,
  229. //bottom: optionsSetup.longitudinalPosition,
  230. orient: optionsSetup.layoutFront,
  231. textStyle: {
  232. color: optionsSetup.legendColor,
  233. fontSize: optionsSetup.legendFontSize,
  234. fontWeight: optionsSetup.legendFontWeight,
  235. fontStyle: optionsSetup.legendFontStyle,
  236. fontFamily: optionsSetup.legendFontFamily,
  237. },
  238. itemHeight: optionsSetup.legendHeight,
  239. itemWidth: optionsSetup.legendWidth,
  240. };
  241. this.options.legend = legend;
  242. },
  243. // 图例颜色修改
  244. setOptionsColor() {
  245. const optionsSetup = this.optionsSetup;
  246. const customColor = optionsSetup.customColor;
  247. if (!customColor) return;
  248. const arrColor = [];
  249. for (let i = 0; i < customColor.length; i++) {
  250. arrColor.push(customColor[i].color);
  251. }
  252. this.options.color = arrColor;
  253. this.options = Object.assign({}, this.options);
  254. },
  255. // 数据解析
  256. setOptionsData(e, paramsConfig) {
  257. const optionsData = this.optionsData; // 数据类型 静态 or 动态
  258. // 联动接收者逻辑开始
  259. optionsData.dynamicData = optionsData.dynamicData || {}; // 兼容 dynamicData undefined
  260. const myDynamicData = optionsData.dynamicData;
  261. clearInterval(this.flagInter); // 不管咋,先干掉上一次的定时任务,避免多跑
  262. if (
  263. e &&
  264. optionsData.dataType !== "staticData" &&
  265. Object.keys(myDynamicData.contextData).length
  266. ) {
  267. const keyArr = Object.keys(myDynamicData.contextData);
  268. paramsConfig.forEach((conf) => {
  269. if (keyArr.includes(conf.targetKey)) {
  270. myDynamicData.contextData[conf.targetKey] = e[conf.originKey];
  271. }
  272. });
  273. }
  274. // 联动接收者逻辑结束
  275. optionsData.dataType == "staticData"
  276. ? this.staticDataFn(optionsData.staticData)
  277. : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
  278. },
  279. staticDataFn(val) {
  280. const staticData = typeof val == "string" ? JSON.parse(val) : val;
  281. for (const key in this.options.series) {
  282. if (this.options.series[key].type == "pie") {
  283. this.options.series[key].data = staticData;
  284. }
  285. }
  286. },
  287. dynamicDataFn(val, refreshTime) {
  288. if (!val) return;
  289. if (this.ispreview) {
  290. this.getEchartData(val);
  291. this.flagInter = setInterval(() => {
  292. this.getEchartData(val);
  293. }, refreshTime);
  294. } else {
  295. this.getEchartData(val);
  296. }
  297. },
  298. getEchartData(val) {
  299. const data = this.queryEchartsData(val);
  300. data.then((res) => {
  301. this.renderingFn(res);
  302. });
  303. },
  304. renderingFn(val) {
  305. for (const key in this.options.series) {
  306. if (this.options.series[key].type == "pie") {
  307. this.options.series[key].data = val;
  308. }
  309. }
  310. },
  311. },
  312. };
  313. </script>
  314. <style scoped lang="scss">
  315. .echarts {
  316. width: 100%;
  317. height: 100%;
  318. overflow: hidden;
  319. }
  320. </style>