You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

transform-single-session.ts 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { Data, Edge, Corner } from 'types'
  2. import vec from 'utils/vec'
  3. import BaseSession from './base-session'
  4. import commands from 'state/commands'
  5. import { getShapeUtils } from 'state/shape-utils'
  6. import { deepClone, getTransformedBoundingBox } from 'utils'
  7. import tld from 'utils/tld'
  8. export default class TransformSingleSession extends BaseSession {
  9. transformType: Edge | Corner
  10. origin: number[]
  11. scaleX = 1
  12. scaleY = 1
  13. snapshot: TransformSingleSnapshot
  14. isCreating: boolean
  15. constructor(
  16. data: Data,
  17. transformType: Corner | Edge,
  18. point: number[],
  19. isCreating = false
  20. ) {
  21. super(data)
  22. this.origin = point
  23. this.transformType = transformType
  24. this.snapshot = getTransformSingleSnapshot(data, transformType)
  25. this.isCreating = isCreating
  26. }
  27. update(data: Data, point: number[], isAspectRatioLocked = false): void {
  28. const { transformType } = this
  29. const { initialShapeBounds, initialShape, id } = this.snapshot
  30. const shape = tld.getShape(data, id)
  31. const newBoundingBox = getTransformedBoundingBox(
  32. initialShapeBounds,
  33. transformType,
  34. vec.vec(this.origin, point),
  35. shape.rotation,
  36. isAspectRatioLocked || !getShapeUtils(initialShape).canChangeAspectRatio
  37. )
  38. this.scaleX = newBoundingBox.scaleX
  39. this.scaleY = newBoundingBox.scaleY
  40. getShapeUtils(shape).transformSingle(shape, newBoundingBox, {
  41. initialShape,
  42. type: this.transformType,
  43. scaleX: this.scaleX,
  44. scaleY: this.scaleY,
  45. transformOrigin: [0.5, 0.5],
  46. })
  47. data.document.pages[data.currentPageId].shapes[shape.id] = deepClone(shape)
  48. tld.updateParents(data, [id])
  49. }
  50. cancel(data: Data): void {
  51. const { id, initialShape } = this.snapshot
  52. const page = tld.getPage(data)
  53. page.shapes[id] = initialShape
  54. tld.updateParents(data, [id])
  55. }
  56. complete(data: Data): void {
  57. if (!this.snapshot.hasUnlockedShape) return
  58. commands.transformSingle(
  59. data,
  60. this.snapshot,
  61. getTransformSingleSnapshot(data, this.transformType),
  62. this.isCreating
  63. )
  64. }
  65. }
  66. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  67. export function getTransformSingleSnapshot(
  68. data: Data,
  69. transformType: Edge | Corner
  70. ) {
  71. const shape = deepClone(tld.getSelectedShapes(data)[0])
  72. const bounds = getShapeUtils(shape).getBounds(shape)
  73. return {
  74. id: shape.id,
  75. hasUnlockedShape: !shape.isLocked,
  76. currentPageId: data.currentPageId,
  77. type: transformType,
  78. initialShape: shape,
  79. initialShapeBounds: bounds,
  80. }
  81. }
  82. export type TransformSingleSnapshot = ReturnType<
  83. typeof getTransformSingleSnapshot
  84. >