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-ccw.ts 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import Command from './command'
  2. import history from '../history'
  3. import { Data } from 'types'
  4. import {
  5. getBoundsCenter,
  6. getCommonBounds,
  7. getPage,
  8. getSelectedShapes,
  9. } from 'utils/utils'
  10. import vec from 'utils/vec'
  11. import { getShapeUtils } from 'lib/shape-utils'
  12. const PI2 = Math.PI * 2
  13. export default function rotateCcwCommand(data: Data) {
  14. const { currentPageId, boundsRotation } = data
  15. const page = getPage(data)
  16. const initialShapes = Object.fromEntries(
  17. getSelectedShapes(data).map((shape) => {
  18. const bounds = getShapeUtils(shape).getBounds(shape)
  19. return [
  20. shape.id,
  21. {
  22. rotation: shape.rotation,
  23. point: [...shape.point],
  24. center: getBoundsCenter(bounds),
  25. bounds,
  26. },
  27. ]
  28. })
  29. )
  30. const commonBoundsCenter = getBoundsCenter(
  31. getCommonBounds(...Object.values(initialShapes).map((b) => b.bounds))
  32. )
  33. const nextShapes = Object.fromEntries(
  34. Object.entries(initialShapes).map(([id, { point, center }]) => {
  35. const shape = { ...page.shapes[id] }
  36. const offset = vec.sub(center, point)
  37. const nextPoint = vec.sub(
  38. vec.rotWith(center, commonBoundsCenter, -(PI2 / 4)),
  39. offset
  40. )
  41. const rot = (PI2 + (shape.rotation - PI2 / 4)) % PI2
  42. getShapeUtils(shape)
  43. .setProperty(shape, 'rotation', rot)
  44. .setProperty(shape, 'point', nextPoint)
  45. return [id, shape]
  46. })
  47. )
  48. const nextboundsRotation = (PI2 + (data.boundsRotation - PI2 / 4)) % PI2
  49. history.execute(
  50. data,
  51. new Command({
  52. name: 'rotate_ccw',
  53. category: 'canvas',
  54. do(data) {
  55. const { shapes } = getPage(data, currentPageId)
  56. for (let id in nextShapes) {
  57. const shape = shapes[id]
  58. if (shape.isLocked) continue
  59. getShapeUtils(shape)
  60. .setProperty(shape, 'rotation', nextShapes[id].rotation)
  61. .setProperty(shape, 'point', nextShapes[id].point)
  62. }
  63. data.boundsRotation = nextboundsRotation
  64. },
  65. undo(data) {
  66. const { shapes } = getPage(data, currentPageId)
  67. for (let id in initialShapes) {
  68. const { point, rotation } = initialShapes[id]
  69. const shape = shapes[id]
  70. if (shape.isLocked) continue
  71. const utils = getShapeUtils(shape)
  72. utils
  73. .setProperty(shape, 'rotation', rotation)
  74. .setProperty(shape, 'point', point)
  75. }
  76. data.boundsRotation = boundsRotation
  77. },
  78. })
  79. )
  80. }