選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

state.ts 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { createSelectorHook, createState } from "@state-designer/react"
  2. import { clamp, screenToWorld } from "utils/utils"
  3. import * as vec from "utils/vec"
  4. import { Data } from "types"
  5. import { defaultDocument } from "./data"
  6. import * as Sessions from "./sessions"
  7. const initialData: Data = {
  8. camera: {
  9. point: [0, 0],
  10. zoom: 1,
  11. },
  12. brush: undefined,
  13. pointedId: null,
  14. selectedIds: [],
  15. currentPageId: "page0",
  16. document: defaultDocument,
  17. }
  18. const state = createState({
  19. data: initialData,
  20. on: {
  21. ZOOMED_CAMERA: {
  22. do: "zoomCamera",
  23. },
  24. PANNED_CAMERA: {
  25. do: "panCamera",
  26. },
  27. },
  28. initial: "selecting",
  29. states: {
  30. selecting: {
  31. on: {
  32. POINTED_CANVAS: { to: "brushSelecting" },
  33. },
  34. },
  35. brushSelecting: {
  36. onEnter: "startBrushSession",
  37. on: {
  38. MOVED_POINTER: "updateBrushSession",
  39. PANNED_CAMERA: "updateBrushSession",
  40. STOPPED_POINTING: { do: "completeSession", to: "selecting" },
  41. CANCELLED: { do: "cancelSession", to: "selecting" },
  42. },
  43. },
  44. },
  45. actions: {
  46. cancelSession(data) {
  47. session.cancel(data)
  48. session = undefined
  49. },
  50. completeSession(data) {
  51. session.complete(data)
  52. session = undefined
  53. },
  54. startBrushSession(data, payload: { point: number[] }) {
  55. session = new Sessions.BrushSession(
  56. data,
  57. screenToWorld(payload.point, data)
  58. )
  59. },
  60. updateBrushSession(data, payload: { point: number[] }) {
  61. session.update(data, screenToWorld(payload.point, data))
  62. },
  63. zoomCamera(data, payload: { delta: number; point: number[] }) {
  64. const { camera } = data
  65. const p0 = screenToWorld(payload.point, data)
  66. camera.zoom = clamp(
  67. camera.zoom - (payload.delta / 100) * camera.zoom,
  68. 0.5,
  69. 3
  70. )
  71. const p1 = screenToWorld(payload.point, data)
  72. camera.point = vec.add(camera.point, vec.sub(p1, p0))
  73. },
  74. panCamera(data, payload: { delta: number[]; point: number[] }) {
  75. const { camera } = data
  76. data.camera.point = vec.sub(
  77. camera.point,
  78. vec.div(payload.delta, camera.zoom)
  79. )
  80. },
  81. },
  82. })
  83. let session: Sessions.BaseSession
  84. export default state
  85. export const useSelector = createSelectorHook(state)