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

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