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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { current } from 'immer'
  2. import { Data, DrawShape } from 'types'
  3. import BaseSession from './base-session'
  4. import { getShapeUtils } from 'lib/shape-utils'
  5. import { getPage } from 'utils/utils'
  6. import * as vec from 'utils/vec'
  7. import commands from 'state/commands'
  8. let prevEndPoint: number[]
  9. export default class BrushSession extends BaseSession {
  10. origin: number[]
  11. previous: number[]
  12. points: number[][]
  13. snapshot: DrawSnapshot
  14. isLocked: boolean
  15. lockedDirection: 'horizontal' | 'vertical'
  16. constructor(data: Data, id: string, point: number[], isLocked = false) {
  17. super(data)
  18. this.origin = point
  19. this.previous = point
  20. this.points = []
  21. this.snapshot = getDrawSnapshot(data, id)
  22. // if (isLocked && prevEndPoint) {
  23. // const continuedPt = vec.sub([...prevEndPoint], this.origin)
  24. // this.points.push(continuedPt)
  25. // }
  26. const page = getPage(data)
  27. const shape = page.shapes[id]
  28. getShapeUtils(shape).translateTo(shape, point)
  29. }
  30. update = (data: Data, point: number[], isLocked = false) => {
  31. const { snapshot } = this
  32. const delta = vec.vec(this.origin, point)
  33. if (isLocked) {
  34. if (!this.isLocked && this.points.length > 1) {
  35. this.isLocked = true
  36. const returning = [...this.previous]
  37. if (Math.abs(delta[0]) < Math.abs(delta[1])) {
  38. this.lockedDirection = 'vertical'
  39. returning[0] = this.origin[0]
  40. } else {
  41. this.lockedDirection = 'horizontal'
  42. returning[1] = this.origin[1]
  43. }
  44. this.previous = returning
  45. this.points.push(vec.sub(returning, this.origin))
  46. }
  47. } else {
  48. if (this.isLocked) {
  49. this.isLocked = false
  50. }
  51. }
  52. if (this.isLocked) {
  53. if (this.lockedDirection === 'vertical') {
  54. point[0] = this.origin[0]
  55. } else {
  56. point[1] = this.origin[1]
  57. }
  58. }
  59. if (this.previous) {
  60. point = vec.med(this.previous, point)
  61. }
  62. prevEndPoint = [...point]
  63. const next = vec.sub(point, this.origin)
  64. this.points.push(next)
  65. this.previous = point
  66. const page = getPage(data)
  67. const shape = page.shapes[snapshot.id] as DrawShape
  68. getShapeUtils(shape).setProperty(shape, 'points', [...this.points])
  69. }
  70. cancel = (data: Data) => {
  71. const { snapshot } = this
  72. const page = getPage(data)
  73. const shape = page.shapes[snapshot.id] as DrawShape
  74. getShapeUtils(shape).setProperty(shape, 'points', snapshot.points)
  75. }
  76. complete = (data: Data) => {
  77. if (this.points.length > 1) {
  78. let minX = Infinity
  79. let minY = Infinity
  80. const pts = [...this.points]
  81. for (let pt of pts) {
  82. minX = Math.min(pt[0], minX)
  83. minY = Math.min(pt[1], minY)
  84. }
  85. for (let pt of pts) {
  86. pt[0] -= minX
  87. pt[1] -= minY
  88. }
  89. const { snapshot } = this
  90. const page = getPage(data)
  91. const shape = page.shapes[snapshot.id] as DrawShape
  92. getShapeUtils(shape)
  93. .setProperty(shape, 'points', pts)
  94. .translateTo(shape, vec.add(shape.point, [minX, minY]))
  95. }
  96. commands.draw(data, this.snapshot.id, this.points)
  97. }
  98. }
  99. export function getDrawSnapshot(data: Data, shapeId: string) {
  100. const page = getPage(current(data))
  101. const { points, style } = page.shapes[shapeId] as DrawShape
  102. return {
  103. id: shapeId,
  104. points,
  105. strokeWidth: style.strokeWidth,
  106. }
  107. }
  108. export type DrawSnapshot = ReturnType<typeof getDrawSnapshot>