template.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. import { defineStore } from 'pinia'
  2. import { Templates } from '@/mocks/templates'
  3. import { Template, CanvasElement, ImageElement, GroupElement, RectElement } from '@/types/canvas'
  4. import { FabricObject, SerializedImageProps, FabricImage, Group, StaticCanvas } from 'fabric'
  5. import { WorkSpaceDrawType, propertiesToInclude } from '@/configs/canvas'
  6. import { useMainStore } from './main'
  7. import { ElementNames } from '@/types/elements'
  8. import { ElLoading } from 'element-plus'
  9. import { Snapshot, SnapshotType } from '@/types/history'
  10. import useCanvasScale from '@/hooks/useCanvasScale'
  11. import useCanvas from '@/views/Canvas/useCanvas'
  12. import useHistorySnapshot from '@/hooks/useHistorySnapshot'
  13. import useCommon from '@/views/Canvas/useCommon'
  14. import usePixi from '@/views/Canvas/usePixi'
  15. interface UpdateElementData {
  16. id: string | string[]
  17. left?: number
  18. top?: number
  19. props: Partial<CanvasElement>
  20. }
  21. export interface TemplatesState {
  22. templateId: string
  23. templateName: string
  24. templates: Template[]
  25. templateIndex: number
  26. templateCanvas: Map<string, StaticCanvas>
  27. }
  28. export const useTemplatesStore = defineStore('Templates', {
  29. state: (): TemplatesState => ({
  30. // theme: theme, // 主题样式
  31. templateId: '',
  32. templateName: '空白模板',
  33. templates: Templates, // 页面页面数据
  34. templateIndex: 0, // 当前页面索引
  35. templateCanvas: new Map()
  36. // fixedRatio: false, // 固定比例
  37. // slideUnit: 'mm', // 尺寸单位
  38. // slideName: '', // 模板名称
  39. // slideId: '', // 模板id
  40. }),
  41. getters: {
  42. currentTemplate(state) {
  43. return state.templates[state.templateIndex] as Template
  44. },
  45. currentTemplateWidth(state) {
  46. const currentTemplate = state.templates[state.templateIndex]
  47. return currentTemplate.width / currentTemplate.zoom
  48. },
  49. currentTemplateHeight(state) {
  50. const currentTemplate = state.templates[state.templateIndex]
  51. return currentTemplate.height / currentTemplate.zoom
  52. },
  53. currentTemplateElement(state) {
  54. const currentTemplate = state.templates[state.templateIndex]
  55. const [ canvas ] = useCanvas()
  56. const activeObject = canvas.getActiveObject() as CanvasElement
  57. return currentTemplate.objects.filter(ele => ele.id === activeObject.id)[0]
  58. }
  59. },
  60. actions: {
  61. async renderTemplate() {
  62. const [ canvas ] = useCanvas()
  63. const { initCommon } = useCommon()
  64. const { setCanvasSize } = useCanvasScale()
  65. await canvas.loadFromJSON(this.currentTemplate)
  66. this.setObjectFilter(this.currentTemplate.objects as CanvasElement[])
  67. setCanvasSize()
  68. initCommon()
  69. },
  70. async renderElement() {
  71. const [ canvas ] = useCanvas()
  72. const { initCommon } = useCommon()
  73. const { setCanvasSize } = useCanvasScale()
  74. const mainStore = useMainStore()
  75. canvas.discardActiveObject()
  76. mainStore.setCanvasObject(undefined)
  77. await canvas.loadFromJSON(this.currentTemplate)
  78. setCanvasSize()
  79. initCommon()
  80. },
  81. modifedElement(target: FabricObject, options: Record<string, any>,) {
  82. const [ canvas ] = useCanvas()
  83. const { addHistorySnapshot } = useHistorySnapshot()
  84. const index = canvas._objects.findIndex(item => item.id === target.id)
  85. const data: Snapshot = {
  86. type: SnapshotType.MODIFY,
  87. index,
  88. target: target.toObject(propertiesToInclude),
  89. tid: this.templateId
  90. }
  91. addHistorySnapshot(data)
  92. target.set({...options});
  93. if (options.filters) {
  94. (target as FabricImage).applyFilters();
  95. }
  96. canvas.setActiveObject(target)
  97. canvas.renderAll()
  98. },
  99. addElement(target: FabricObject) {
  100. const [ canvas ] = useCanvas()
  101. const { addHistorySnapshot } = useHistorySnapshot()
  102. const data: Snapshot = {
  103. type: SnapshotType.ADD,
  104. index: canvas._objects.indexOf(target),
  105. target: target.toObject(propertiesToInclude),
  106. tid: this.templateId
  107. }
  108. addHistorySnapshot(data)
  109. },
  110. groupElement(target: FabricObject, objects: FabricObject[]) {
  111. const [ canvas ] = useCanvas()
  112. const { addHistorySnapshot } = useHistorySnapshot()
  113. const data: Snapshot = {
  114. type: SnapshotType.GROUP,
  115. index: canvas._objects.indexOf(target),
  116. target: target.toObject(propertiesToInclude),
  117. objects: objects.map(item => item.toObject(propertiesToInclude)),
  118. tid: this.templateId
  119. }
  120. addHistorySnapshot(data)
  121. },
  122. ungroupElement() {
  123. },
  124. deleteElement(target: FabricObject) {
  125. const [ canvas ] = useCanvas()
  126. const { addHistorySnapshot } = useHistorySnapshot()
  127. const data: Snapshot = {
  128. type: SnapshotType.DELETE,
  129. index: canvas._objects.indexOf(target),
  130. target: target.toObject(propertiesToInclude),
  131. tid: this.templateId
  132. }
  133. canvas.remove(target)
  134. canvas.renderAll()
  135. addHistorySnapshot(data)
  136. },
  137. setClip(clip: number) {
  138. const { addHistorySnapshot } = useHistorySnapshot()
  139. this.templates.forEach(template => {
  140. template.clip = clip
  141. })
  142. // addHistorySnapshot()
  143. },
  144. setSize(width: number, height: number, zoom: number) {
  145. const { initCommon } = useCommon()
  146. const { addHistorySnapshot } = useHistorySnapshot()
  147. this.templates.forEach(template => {
  148. template.width = width
  149. template.height = height
  150. template.zoom = zoom
  151. template.objects.filter(item => item.id === WorkSpaceDrawType).map(ele => {
  152. ele.width = width / zoom
  153. ele.height = height / zoom
  154. })
  155. })
  156. initCommon()
  157. // addHistorySnapshot()
  158. },
  159. setObjectFilter(objects: CanvasElement[]) {
  160. objects.forEach(ele => {
  161. if (ele.type.toLowerCase() === ElementNames.IMAGE) {
  162. this.setImageFilter(ele as ImageElement)
  163. // this.setImageMask(ele as ImageElement)
  164. }
  165. if (ele.type.toLowerCase() === ElementNames.GROUP) {
  166. this.setObjectFilter(((ele as GroupElement).objects) as CanvasElement[])
  167. }
  168. })
  169. },
  170. setImageFilter(image: ImageElement) {
  171. if (!image.pixiFilters) return
  172. const [ pixi ] = usePixi()
  173. pixi.postMessage({
  174. id: image.id,
  175. type: "filter",
  176. src: image.src,
  177. pixiFilters: JSON.stringify(image.pixiFilters),
  178. width: image.width,
  179. height: image.height
  180. });
  181. },
  182. setImageMask(image: ImageElement) {
  183. if (!image.mask) return
  184. const [ pixi ] = usePixi()
  185. pixi.postMessage({
  186. id: image.id,
  187. type: "mask",
  188. src: image.src,
  189. mask: JSON.stringify(image.mask),
  190. width: image.width,
  191. height: image.height
  192. });
  193. },
  194. async changeTemplate(template: Template | Template[]) {
  195. const { setCanvasTransform } = useCanvasScale()
  196. const templates = Array.isArray(template) ? template : [template]
  197. this.templates = templates
  198. this.templateIndex = 0
  199. await this.renderTemplate()
  200. setCanvasTransform()
  201. },
  202. setTemplates(templates: Template[]) {
  203. this.templates = templates
  204. },
  205. setTemplateId(templateId: string) {
  206. this.templateId = templateId
  207. },
  208. setTemplateName(templateName:string){
  209. this.templateName = templateName
  210. },
  211. setTemplateIndex(index: number) {
  212. this.templateIndex = index
  213. },
  214. async addTemplate(template: Template | Template[]) {
  215. const templates = Array.isArray(template) ? template : [template]
  216. const addIndex = this.templateIndex + 1
  217. this.templates.splice(addIndex, 0, ...templates)
  218. this.templateIndex = addIndex
  219. await this.renderTemplate()
  220. },
  221. updateTemplate(props: Partial<Template>) {
  222. const { addHistorySnapshot } = useHistorySnapshot()
  223. const templateIndex = this.templateIndex
  224. this.templates[templateIndex] = { ...this.templates[templateIndex], ...props }
  225. // addHistorySnapshot()
  226. },
  227. deleteTemplate(templateId: string | string[]) {
  228. const { addHistorySnapshot } = useHistorySnapshot()
  229. const templateIds = Array.isArray(templateId) ? templateId : [templateId]
  230. const deleteTemplatesIndex = []
  231. for (let i = 0; i < templateIds.length; i++) {
  232. const index = this.templates.findIndex(item => item.id === templateIds[i])
  233. deleteTemplatesIndex.push(index)
  234. }
  235. let newIndex = Math.min(...deleteTemplatesIndex)
  236. const maxIndex = this.templates.length - templateIds.length - 1
  237. if (newIndex > maxIndex) newIndex = maxIndex
  238. this.templateIndex = newIndex
  239. this.templates = this.templates.filter(item => !templateIds.includes(item.id))
  240. // addHistorySnapshot()
  241. },
  242. clearTemplate() {
  243. const objects = this.templates[this.templateIndex].objects.filter(item => item.id === WorkSpaceDrawType)
  244. this.templates[this.templateIndex].objects = objects
  245. this.renderTemplate()
  246. },
  247. updateWorkSpace(props: Partial<Template>) {
  248. const templateIndex = this.templateIndex
  249. this.templates[templateIndex] = { ...this.templates[templateIndex], ...props }
  250. },
  251. updateElement(data: UpdateElementData) {
  252. const { addHistorySnapshot } = useHistorySnapshot()
  253. const { id, props } = data
  254. const elementIds = typeof id === 'string' ? [id] : id
  255. if (!elementIds) return
  256. const template = this.templates[this.templateIndex]
  257. const elements = template.objects.map(el => elementIds.includes(el.id) ? { ...el, ...props }: el)
  258. this.templates[this.templateIndex].objects = elements as FabricObject[]
  259. // addHistorySnapshot()
  260. },
  261. // addElement(element: FabricObject | FabricObject[]) {
  262. // const { addHistorySnapshot } = useHistorySnapshot()
  263. // const elements = Array.isArray(element) ? element : [element]
  264. // const currentTemplateElements = this.templates[this.templateIndex].objects
  265. // const newElements = [...currentTemplateElements, ...elements]
  266. // this.templates[this.templateIndex].objects = newElements as FabricObject[]
  267. // addHistorySnapshot()
  268. // },
  269. // deleteElement(elementId: string | string[]) {
  270. // const { addHistorySnapshot } = useHistorySnapshot()
  271. // const elementIds = Array.isArray(elementId) ? elementId : [elementId]
  272. // const currentTemplateElements = this.templates[this.templateIndex].objects
  273. // const newElements = currentTemplateElements.filter(item => !elementIds.includes(item.id))
  274. // this.templates[this.templateIndex].objects = newElements
  275. // addHistorySnapshot()
  276. // },
  277. setBackgroundImage(props: SerializedImageProps) {
  278. this.currentTemplate.backgroundImage = props
  279. },
  280. }
  281. })