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.

rotate.command.ts 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { Utils, Vec } from '@tldraw/core'
  2. import type { TLDrawCommand, Data } from '~types'
  3. import { TLDR } from '~state/tldr'
  4. const PI2 = Math.PI * 2
  5. export function rotate(data: Data, ids: string[], delta = -PI2 / 4): TLDrawCommand {
  6. const { currentPageId } = data.appState
  7. const initialShapes = ids.map((id) => TLDR.getShape(data, id, currentPageId))
  8. const boundsForShapes = initialShapes.map((shape) => {
  9. const utils = TLDR.getShapeUtils(shape)
  10. return {
  11. id: shape.id,
  12. point: [...shape.point],
  13. bounds: utils.getBounds(shape),
  14. center: utils.getCenter(shape),
  15. rotation: shape.rotation,
  16. }
  17. })
  18. const commonBounds = Utils.getCommonBounds(boundsForShapes.map(({ bounds }) => bounds))
  19. const commonBoundsCenter = Utils.getBoundsCenter(commonBounds)
  20. const rotations = Object.fromEntries(
  21. boundsForShapes.map(({ id, point, center, rotation }) => {
  22. const offset = Vec.sub(center, point)
  23. const nextPoint = Vec.sub(Vec.rotWith(center, commonBoundsCenter, -(PI2 / 4)), offset)
  24. const nextRotation = (PI2 + ((rotation || 0) + delta)) % PI2
  25. return [id, { point: nextPoint, rotation: nextRotation }]
  26. })
  27. )
  28. const pageState = TLDR.getPageState(data, currentPageId)
  29. const prevBoundsRotation = pageState.boundsRotation
  30. const nextBoundsRotation = (PI2 + ((pageState.boundsRotation || 0) + delta)) % PI2
  31. const { before, after } = TLDR.mutateShapes(
  32. data,
  33. ids,
  34. (shape) => rotations[shape.id],
  35. currentPageId
  36. )
  37. return {
  38. id: 'toggle_shapes',
  39. before: {
  40. document: {
  41. pages: {
  42. [currentPageId]: { shapes: before },
  43. },
  44. pageStates: {
  45. [currentPageId]: { boundsRotation: prevBoundsRotation },
  46. },
  47. },
  48. },
  49. after: {
  50. document: {
  51. pages: {
  52. [currentPageId]: { shapes: after },
  53. },
  54. pageStates: {
  55. [currentPageId]: { boundsRotation: nextBoundsRotation },
  56. },
  57. },
  58. },
  59. }
  60. }