chartEditStore.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import { defineStore } from 'pinia'
  2. import debounce from 'lodash/debounce'
  3. import { loadingStart, loadingFinish, loadingError } from '@/utils'
  4. import { CreateComponentType } from '@/packages/index.d'
  5. import {
  6. chartEditStoreType,
  7. EditCanvasType,
  8. MousePositionType,
  9. TargetChartType
  10. } from './chartEditStore.d'
  11. // 编辑区域内容
  12. export const useChartEditStoreStore = defineStore({
  13. id: 'useChartEditStoreStore',
  14. state: (): chartEditStoreType => ({
  15. // 编辑画布属性
  16. editCanvas: {
  17. // 编辑区域 Dom
  18. editLayoutDom: null,
  19. editContentDom: null,
  20. // 默认宽度
  21. width: 1920,
  22. // 默认高度
  23. height: 1080,
  24. // 偏移量
  25. offset: 20,
  26. // 系统控制缩放
  27. scale: 1,
  28. // 用户控制的缩放
  29. userScale: 1,
  30. // 锁定缩放
  31. lockScale: false,
  32. // 默认背景色
  33. background: undefined
  34. },
  35. // 右键菜单
  36. rightMenuShow: false,
  37. // 鼠标定位
  38. mousePosition: {
  39. x: 0,
  40. y: 0
  41. },
  42. // 目标图表
  43. targetChart: {
  44. hoverId: undefined,
  45. selectId: undefined
  46. },
  47. // 图表数组
  48. componentList: []
  49. }),
  50. getters: {
  51. getMousePosition(): MousePositionType {
  52. return this.mousePosition
  53. },
  54. getRightMenuShow(): boolean {
  55. return this.rightMenuShow
  56. },
  57. getEditCanvas(): EditCanvasType {
  58. return this.editCanvas
  59. },
  60. getTargetChart():TargetChartType {
  61. return this.targetChart
  62. },
  63. getComponentList(): CreateComponentType[] {
  64. return this.componentList
  65. }
  66. },
  67. actions: {
  68. // * 设置 editCanvas 数据项
  69. setEditCanvasItem< T extends keyof EditCanvasType, K extends EditCanvasType[T] >(key: T, value: K) {
  70. this.editCanvas[key] = value
  71. },
  72. // * 设置右键菜单
  73. setRightMenuShow(value: boolean) {
  74. this.rightMenuShow = value
  75. },
  76. // * 设置目标数据 hover
  77. setTargetHoverChart(hoverId?:TargetChartType["hoverId"]) {
  78. this.targetChart.hoverId = hoverId
  79. },
  80. // * 设置目标数据 select
  81. setTargetSelectChart(selectId?:TargetChartType["selectId"]) {
  82. this.targetChart.selectId = selectId
  83. },
  84. // * 找到目标 id 数据下标位置
  85. fetchTargetIndex(): number {
  86. const index = this.componentList.findIndex(e => e.id === this.getTargetChart.selectId)
  87. if (index === -1) {
  88. window['$message'].success(`操作失败,无法找到此元素`)
  89. loadingError()
  90. }
  91. return index
  92. },
  93. // * 新增组件列表
  94. addComponentList(chartData: CreateComponentType, isEnd = false): void {
  95. if(isEnd) {
  96. this.componentList.unshift(chartData)
  97. return
  98. }
  99. this.componentList.push(chartData)
  100. },
  101. // * 删除组件列表
  102. removeComponentList(): void {
  103. try {
  104. loadingStart()
  105. const index = this.fetchTargetIndex()
  106. if (index !== -1) {
  107. this.componentList.splice(index, 1)
  108. loadingFinish()
  109. return
  110. }
  111. } catch(value) {
  112. loadingError()
  113. }
  114. },
  115. // * 更新组件列表某一项的值
  116. updateComponentList(index: number, newData: CreateComponentType) {
  117. if(index < 1 && index > this.getComponentList.length) return
  118. this.componentList[index] = newData
  119. },
  120. // * 移动组件列表位置到两端
  121. setBothEnds(isEnd = false): void {
  122. try {
  123. loadingStart()
  124. const length = this.getComponentList.length
  125. if(length < 2) {
  126. loadingFinish()
  127. return
  128. }
  129. const index = this.fetchTargetIndex()
  130. if (index !== -1) {
  131. // 置底排除最底层, 置顶排除最顶层
  132. if ((isEnd && index === 0) || (!isEnd && index === length - 1 )) {
  133. loadingFinish()
  134. return
  135. }
  136. // 插入两端
  137. this.addComponentList(this.getComponentList[index], isEnd)
  138. this.getComponentList.splice(isEnd ? index + 1: index, 1)
  139. loadingFinish()
  140. return
  141. }
  142. } catch(value) {
  143. loadingError()
  144. }
  145. },
  146. // * 置顶
  147. setTop(): void {
  148. this.setBothEnds()
  149. },
  150. // * 置底
  151. setBottom(): void {
  152. this.setBothEnds(true)
  153. },
  154. // * 设置页面样式属性
  155. setPageStyle<T extends keyof CSSStyleDeclaration>(
  156. key: T,
  157. value: any
  158. ): void {
  159. const dom = this.getEditCanvas.editContentDom
  160. if (dom) {
  161. dom.style[key] = value
  162. }
  163. },
  164. // * 互换图表位置
  165. wrap(isDown = false) {
  166. try {
  167. loadingStart()
  168. const length = this.getComponentList.length
  169. if (length < 2) {
  170. loadingFinish()
  171. return
  172. }
  173. const index:number = this.fetchTargetIndex()
  174. if (index !== -1) {
  175. // 下移排除最底层, 上移排除最顶层
  176. if ((isDown && index === 0) || (!isDown && index === length - 1)) {
  177. loadingFinish()
  178. return
  179. }
  180. // 互换位置
  181. const swapIndex = isDown ? index - 1 : index + 1
  182. const targetItem = this.getComponentList[index]
  183. const swapItem = this.getComponentList[swapIndex]
  184. this.updateComponentList(index, swapItem)
  185. this.updateComponentList(swapIndex, targetItem)
  186. loadingFinish()
  187. return
  188. }
  189. } catch(value) {
  190. loadingError()
  191. }
  192. },
  193. // * 上移
  194. setUp() {
  195. this.wrap()
  196. },
  197. // * 下移
  198. setDown() {
  199. this.wrap(true)
  200. },
  201. // * 设置页面变换时候的 Class
  202. setPageSizeClass(): void {
  203. const dom = this.getEditCanvas.editContentDom
  204. if (dom) {
  205. dom.classList.add('content-resize')
  206. setTimeout(() => {
  207. dom.classList.remove('content-resize')
  208. }, 600)
  209. }
  210. },
  211. // * 设置页面大小
  212. setPageSize(): void {
  213. this.setPageStyle('height', `${this.getEditCanvas.height}px`)
  214. this.setPageStyle('width', `${this.getEditCanvas.width}px`)
  215. },
  216. // * 设置鼠标位置
  217. setMousePosition(x: number, y: number): void {
  218. this.mousePosition.x = x
  219. this.mousePosition.y = y
  220. },
  221. // * 计算缩放
  222. computedScale() {
  223. if (this.getEditCanvas.editLayoutDom) {
  224. // 现有展示区域
  225. const width =
  226. this.getEditCanvas.editLayoutDom.clientWidth - this.getEditCanvas.offset * 2 - 5
  227. const height =
  228. this.getEditCanvas.editLayoutDom.clientHeight - this.getEditCanvas.offset * 4
  229. // 用户设定大小
  230. const editCanvasWidth = this.getEditCanvas.width
  231. const editCanvasHeight = this.getEditCanvas.height
  232. // 需保持的比例
  233. const baseProportion = parseFloat(
  234. (editCanvasWidth / editCanvasHeight).toFixed(5)
  235. )
  236. const currentRate = parseFloat((width / height).toFixed(5))
  237. if (currentRate > baseProportion) {
  238. // 表示更宽
  239. const scaleWidth = parseFloat(
  240. ((height * baseProportion) / editCanvasWidth).toFixed(5)
  241. )
  242. this.setScale( scaleWidth > 1 ? 1 : scaleWidth)
  243. } else {
  244. // 表示更高
  245. const scaleHeight = parseFloat(
  246. (width / baseProportion / editCanvasHeight).toFixed(5)
  247. )
  248. this.setScale(scaleHeight > 1 ? 1 : scaleHeight)
  249. }
  250. } else {
  251. window['$message'].warning('请先创建画布,再进行缩放')
  252. }
  253. },
  254. // * 监听缩放
  255. listenerScale(): Function {
  256. const resize = debounce(this.computedScale, 200)
  257. // 默认执行一次
  258. resize()
  259. // 开始监听
  260. window.addEventListener('resize', resize)
  261. // 销毁函数
  262. const remove = () => {
  263. window.removeEventListener('resize', resize)
  264. }
  265. return remove
  266. },
  267. // * 设置缩放
  268. setScale(scale: number, sys = true): void {
  269. if (!this.getEditCanvas.lockScale) {
  270. this.setPageSizeClass()
  271. this.setPageStyle('transform', `scale(${scale})`)
  272. this.getEditCanvas.userScale = scale
  273. if (sys) {
  274. this.getEditCanvas.scale = scale
  275. }
  276. }
  277. }
  278. }
  279. })