next2d-development-mcp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +344 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +16 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/prompts/index.d.ts +3 -0
  7. package/dist/prompts/index.d.ts.map +1 -0
  8. package/dist/prompts/index.js +211 -0
  9. package/dist/prompts/index.js.map +1 -0
  10. package/dist/prompts/prompts.test.d.ts +2 -0
  11. package/dist/prompts/prompts.test.d.ts.map +1 -0
  12. package/dist/prompts/prompts.test.js +23 -0
  13. package/dist/prompts/prompts.test.js.map +1 -0
  14. package/dist/references/develop-specs.md +1576 -0
  15. package/dist/references/framework-specs.md +1687 -0
  16. package/dist/references/player-specs.md +3292 -0
  17. package/dist/resources/index.d.ts +3 -0
  18. package/dist/resources/index.d.ts.map +1 -0
  19. package/dist/resources/index.js +185 -0
  20. package/dist/resources/index.js.map +1 -0
  21. package/dist/resources/resources.test.d.ts +2 -0
  22. package/dist/resources/resources.test.d.ts.map +1 -0
  23. package/dist/resources/resources.test.js +32 -0
  24. package/dist/resources/resources.test.js.map +1 -0
  25. package/dist/templates/animation.d.ts +6 -0
  26. package/dist/templates/animation.d.ts.map +1 -0
  27. package/dist/templates/animation.js +65 -0
  28. package/dist/templates/animation.js.map +1 -0
  29. package/dist/templates/animation.test.d.ts +2 -0
  30. package/dist/templates/animation.test.d.ts.map +1 -0
  31. package/dist/templates/animation.test.js +30 -0
  32. package/dist/templates/animation.test.js.map +1 -0
  33. package/dist/templates/domainService.d.ts +9 -0
  34. package/dist/templates/domainService.d.ts.map +1 -0
  35. package/dist/templates/domainService.js +56 -0
  36. package/dist/templates/domainService.js.map +1 -0
  37. package/dist/templates/domainService.test.d.ts +2 -0
  38. package/dist/templates/domainService.test.d.ts.map +1 -0
  39. package/dist/templates/domainService.test.js +33 -0
  40. package/dist/templates/domainService.test.js.map +1 -0
  41. package/dist/templates/interfaceFile.d.ts +5 -0
  42. package/dist/templates/interfaceFile.d.ts.map +1 -0
  43. package/dist/templates/interfaceFile.js +16 -0
  44. package/dist/templates/interfaceFile.js.map +1 -0
  45. package/dist/templates/interfaceFile.test.d.ts +2 -0
  46. package/dist/templates/interfaceFile.test.d.ts.map +1 -0
  47. package/dist/templates/interfaceFile.test.js +30 -0
  48. package/dist/templates/interfaceFile.test.js.map +1 -0
  49. package/dist/templates/loading.d.ts +5 -0
  50. package/dist/templates/loading.d.ts.map +1 -0
  51. package/dist/templates/loading.js +62 -0
  52. package/dist/templates/loading.js.map +1 -0
  53. package/dist/templates/loading.test.d.ts +2 -0
  54. package/dist/templates/loading.test.d.ts.map +1 -0
  55. package/dist/templates/loading.test.js +31 -0
  56. package/dist/templates/loading.test.js.map +1 -0
  57. package/dist/templates/repository.d.ts +2 -0
  58. package/dist/templates/repository.d.ts.map +1 -0
  59. package/dist/templates/repository.js +42 -0
  60. package/dist/templates/repository.js.map +1 -0
  61. package/dist/templates/repository.test.d.ts +2 -0
  62. package/dist/templates/repository.test.d.ts.map +1 -0
  63. package/dist/templates/repository.test.js +44 -0
  64. package/dist/templates/repository.test.js.map +1 -0
  65. package/dist/templates/uiComponent.d.ts +4 -0
  66. package/dist/templates/uiComponent.d.ts.map +1 -0
  67. package/dist/templates/uiComponent.js +108 -0
  68. package/dist/templates/uiComponent.js.map +1 -0
  69. package/dist/templates/uiComponent.test.d.ts +2 -0
  70. package/dist/templates/uiComponent.test.d.ts.map +1 -0
  71. package/dist/templates/uiComponent.test.js +76 -0
  72. package/dist/templates/uiComponent.test.js.map +1 -0
  73. package/dist/templates/usecase.d.ts +2 -0
  74. package/dist/templates/usecase.d.ts.map +1 -0
  75. package/dist/templates/usecase.js +31 -0
  76. package/dist/templates/usecase.js.map +1 -0
  77. package/dist/templates/usecase.test.d.ts +2 -0
  78. package/dist/templates/usecase.test.d.ts.map +1 -0
  79. package/dist/templates/usecase.test.js +23 -0
  80. package/dist/templates/usecase.test.js.map +1 -0
  81. package/dist/templates/view.d.ts +3 -0
  82. package/dist/templates/view.d.ts.map +1 -0
  83. package/dist/templates/view.js +112 -0
  84. package/dist/templates/view.js.map +1 -0
  85. package/dist/templates/view.test.d.ts +2 -0
  86. package/dist/templates/view.test.d.ts.map +1 -0
  87. package/dist/templates/view.test.js +71 -0
  88. package/dist/templates/view.test.js.map +1 -0
  89. package/dist/tools/addRoute.d.ts +3 -0
  90. package/dist/tools/addRoute.d.ts.map +1 -0
  91. package/dist/tools/addRoute.js +101 -0
  92. package/dist/tools/addRoute.js.map +1 -0
  93. package/dist/tools/createAnimation.d.ts +3 -0
  94. package/dist/tools/createAnimation.d.ts.map +1 -0
  95. package/dist/tools/createAnimation.js +53 -0
  96. package/dist/tools/createAnimation.js.map +1 -0
  97. package/dist/tools/createDomainService.d.ts +3 -0
  98. package/dist/tools/createDomainService.d.ts.map +1 -0
  99. package/dist/tools/createDomainService.js +82 -0
  100. package/dist/tools/createDomainService.js.map +1 -0
  101. package/dist/tools/createInterface.d.ts +3 -0
  102. package/dist/tools/createInterface.d.ts.map +1 -0
  103. package/dist/tools/createInterface.js +59 -0
  104. package/dist/tools/createInterface.js.map +1 -0
  105. package/dist/tools/createLoading.d.ts +3 -0
  106. package/dist/tools/createLoading.d.ts.map +1 -0
  107. package/dist/tools/createLoading.js +52 -0
  108. package/dist/tools/createLoading.js.map +1 -0
  109. package/dist/tools/createRepository.d.ts +3 -0
  110. package/dist/tools/createRepository.d.ts.map +1 -0
  111. package/dist/tools/createRepository.js +55 -0
  112. package/dist/tools/createRepository.js.map +1 -0
  113. package/dist/tools/createUiComponent.d.ts +3 -0
  114. package/dist/tools/createUiComponent.d.ts.map +1 -0
  115. package/dist/tools/createUiComponent.js +80 -0
  116. package/dist/tools/createUiComponent.js.map +1 -0
  117. package/dist/tools/createUseCase.d.ts +3 -0
  118. package/dist/tools/createUseCase.d.ts.map +1 -0
  119. package/dist/tools/createUseCase.js +52 -0
  120. package/dist/tools/createUseCase.js.map +1 -0
  121. package/dist/tools/createView.d.ts +3 -0
  122. package/dist/tools/createView.d.ts.map +1 -0
  123. package/dist/tools/createView.js +59 -0
  124. package/dist/tools/createView.js.map +1 -0
  125. package/dist/tools/index.d.ts +5 -0
  126. package/dist/tools/index.d.ts.map +1 -0
  127. package/dist/tools/index.js +25 -0
  128. package/dist/tools/index.js.map +1 -0
  129. package/dist/tools/tools.test.d.ts +2 -0
  130. package/dist/tools/tools.test.d.ts.map +1 -0
  131. package/dist/tools/tools.test.js +58 -0
  132. package/dist/tools/tools.test.js.map +1 -0
  133. package/dist/tools/validateArchitecture.d.ts +3 -0
  134. package/dist/tools/validateArchitecture.d.ts.map +1 -0
  135. package/dist/tools/validateArchitecture.js +134 -0
  136. package/dist/tools/validateArchitecture.js.map +1 -0
  137. package/dist/utils.d.ts +10 -0
  138. package/dist/utils.d.ts.map +1 -0
  139. package/dist/utils.js +18 -0
  140. package/dist/utils.js.map +1 -0
  141. package/dist/utils.test.d.ts +2 -0
  142. package/dist/utils.test.d.ts.map +1 -0
  143. package/dist/utils.test.js +34 -0
  144. package/dist/utils.test.js.map +1 -0
  145. package/package.json +48 -0
@@ -0,0 +1,1687 @@
1
+ # Next2D Framework Specs - Combined Reference
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [Index - フレームワーク概要](#index---フレームワーク概要)
6
+ 2. [AnimationTool連携](#animationtool連携)
7
+ 3. [設定ファイル](#設定ファイル)
8
+ 4. [ルーティング](#ルーティング)
9
+ 5. [View と ViewModel](#view-と-viewmodel)
10
+
11
+ ---
12
+
13
+ # Index - フレームワーク概要
14
+
15
+ Next2D Framework is an MVVM framework for application development using the Next2D Player. It provides routing, View/ViewModel management, configuration management, and other features for single-page applications (SPAs).
16
+
17
+ ## Key Features
18
+
19
+ - **MVVM Pattern**: Separation of concerns through Model-View-ViewModel architecture
20
+ - **Clean Architecture**: Dependency inversion and loosely coupled design
21
+ - **Single Page Application**: Scene management based on URLs
22
+ - **Animation Tool Integration**: Integration with assets created in Animation Tool
23
+ - **TypeScript Support**: Type-safe development capability
24
+ - **Atomic Design**: Component design promoting reusability
25
+
26
+ ## Architecture Overview
27
+
28
+ This project combines clean architecture with the MVVM pattern.
29
+
30
+ ```mermaid
31
+ graph TB
32
+ subgraph ViewLayer["View Layer"]
33
+ View["View"]
34
+ ViewModel["ViewModel"]
35
+ UI["UI Components"]
36
+ end
37
+
38
+ subgraph InterfaceLayer["Interface Layer"]
39
+ IDraggable["IDraggable"]
40
+ ITextField["ITextField"]
41
+ IResponse["IResponse"]
42
+ end
43
+
44
+ subgraph ApplicationLayer["Application Layer"]
45
+ UseCase["UseCase"]
46
+ end
47
+
48
+ subgraph DomainLayer["Domain Layer"]
49
+ DomainLogic["Domain Logic"]
50
+ DomainService["Service"]
51
+ end
52
+
53
+ subgraph InfraLayer["Infrastructure Layer"]
54
+ Repository["Repository"]
55
+ ExternalAPI["External API"]
56
+ end
57
+
58
+ ViewLayer -.->|interface経由| InterfaceLayer
59
+ ViewLayer -.->|calls| ApplicationLayer
60
+ ApplicationLayer -.->|interface経由| InterfaceLayer
61
+ ApplicationLayer -.->|uses| DomainLayer
62
+ ApplicationLayer -.->|calls| InfraLayer
63
+ InfraLayer -.->|accesses| ExternalAPI
64
+ ```
65
+
66
+ ### Layer Responsibilities
67
+
68
+ | Layer | Path | Role |
69
+ |----------|------|------|
70
+ | **View** | `view/*`, `ui/*` | Screen structure and display |
71
+ | **ViewModel** | `view/*` | Bridging View and Model, event handling |
72
+ | **Interface** | `interface/*` | Abstraction layer, type definitions |
73
+ | **Application** | `model/application/*/usecase/*` | Business logic implementation (UseCase) |
74
+ | **Domain** | `model/domain/*` | Core business rules |
75
+ | **Infrastructure** | `model/infrastructure/repository/*` | Data access, external API integration |
76
+
77
+ ### Dependency Direction
78
+
79
+ Following clean architecture principles, dependencies always point inward toward the Domain layer.
80
+
81
+ - **View Layer**: Uses Application layer through interfaces
82
+ - **Application Layer**: Uses Domain and Infrastructure layers through interfaces
83
+ - **Domain Layer**: Depends on nothing (pure business logic)
84
+ - **Infrastructure Layer**: Implements Domain layer interfaces
85
+
86
+ ## Directory Structure
87
+
88
+ ```
89
+ my-app/
90
+ ├── src/
91
+ │ ├── config/ # Configuration files
92
+ │ │ ├── stage.json # Stage configuration
93
+ │ │ ├── config.json # Environment configuration
94
+ │ │ ├── routing.json # Routing configuration
95
+ │ │ └── Config.ts # Type definitions and exports
96
+ │ │
97
+ │ ├── interface/ # Interface definitions
98
+ │ │ ├── IDraggable.ts # Draggable objects
99
+ │ │ ├── ITextField.ts # Text field interface
100
+ │ │ ├── IHomeTextResponse.ts # API response type
101
+ │ │ └── IViewName.ts # Screen name type definition
102
+ │ │
103
+ │ ├── view/ # View & ViewModel
104
+ │ │ ├── top/
105
+ │ │ │ ├── TopView.ts # Screen structure definition
106
+ │ │ │ └── TopViewModel.ts # Business logic bridge
107
+ │ │ └── home/
108
+ │ │ ├── HomeView.ts
109
+ │ │ └── HomeViewModel.ts
110
+ │ │
111
+ │ ├── model/
112
+ │ │ ├── application/ # Application layer
113
+ │ │ │ ├── top/
114
+ │ │ │ │ └── usecase/
115
+ │ │ │ │ └── NavigateToViewUseCase.ts
116
+ │ │ │ └── home/
117
+ │ │ │ └── usecase/
118
+ │ │ │ ├── StartDragUseCase.ts
119
+ │ │ │ ├── StopDragUseCase.ts
120
+ │ │ │ └── CenterTextFieldUseCase.ts
121
+ │ │ │
122
+ │ │ ├── domain/ # Domain layer
123
+ │ │ │ └── callback/
124
+ │ │ │ ├── Background.ts
125
+ │ │ │ └── Background/
126
+ │ │ │ └── service/
127
+ │ │ │ ├── BackgroundDrawService.ts
128
+ │ │ │ └── BackgroundChangeScaleService.ts
129
+ │ │ │
130
+ │ │ └── infrastructure/ # Infrastructure layer
131
+ │ │ └── repository/
132
+ │ │ └── HomeTextRepository.ts
133
+ │ │
134
+ │ ├── ui/ # UI components
135
+ │ │ ├── animation/ # Animation definitions
136
+ │ │ │ └── top/
137
+ │ │ │ └── TopBtnShowAnimation.ts
138
+ │ │ │
139
+ │ │ ├── component/ # Atomic design
140
+ │ │ │ ├── atom/ # Minimal unit components
141
+ │ │ │ │ ├── ButtonAtom.ts
142
+ │ │ │ │ └── TextAtom.ts
143
+ │ │ │ ├── molecule/ # Combined atoms
144
+ │ │ │ │ ├── HomeBtnMolecule.ts
145
+ │ │ │ │ └── TopBtnMolecule.ts
146
+ │ │ │ ├── organism/ # Multiple molecules combined
147
+ │ │ │ ├── template/ # Page templates
148
+ │ │ │ └── page/ # Page components
149
+ │ │ │ ├── top/
150
+ │ │ │ │ └── TopPage.ts
151
+ │ │ │ └── home/
152
+ │ │ │ └── HomePage.ts
153
+ │ │ │
154
+ │ │ └── content/ # Animation Tool generated content
155
+ │ │ ├── TopContent.ts
156
+ │ │ └── HomeContent.ts
157
+ │ │
158
+ │ ├── assets/ # Static assets
159
+ │ │
160
+ │ ├── Packages.ts # Package exports
161
+ │ └── index.ts # Entry point
162
+
163
+ ├── file/ # Animation Tool output files
164
+ │ └── sample.n2d
165
+
166
+ ├── mock/ # Mock data
167
+ │ ├── api/ # API mocks
168
+ │ ├── content/ # Content mocks
169
+ │ └── img/ # Image mocks
170
+
171
+ └── package.json
172
+ ```
173
+
174
+ ## Framework Flowchart
175
+
176
+ Detailed flow of screen transitions via the gotoView function.
177
+
178
+ ```mermaid
179
+ graph TD
180
+ User([User]) -->|Request| GotoView[gotoView Path]
181
+
182
+ GotoView --> LoadingCheck{use loading?<br/>Default: true}
183
+
184
+ LoadingCheck -->|YES| ScreenOverlay[Screen Overlay]
185
+ LoadingCheck -->|NO| RemoveResponse
186
+ ScreenOverlay --> LoadingStart[Start Loading]
187
+ LoadingStart --> RemoveResponse
188
+
189
+ RemoveResponse[Remove Previous Response Data] --> ParseQuery[Parse Query String]
190
+ ParseQuery --> UpdateHistory{SPA mode?}
191
+
192
+ UpdateHistory -->|YES| PushState[Push History State]
193
+ UpdateHistory -->|NO| RequestType
194
+ PushState --> RequestType
195
+
196
+ RequestType[Request Type]
197
+
198
+ RequestType --> JSON[JSON: Get external JSON data]
199
+ RequestType --> CONTENT[CONTENT: Get Animation Tool JSON]
200
+ RequestType --> CUSTOM[CUSTOM: Request to external API]
201
+
202
+ JSON --> CacheCheck{use cache?<br/>Default: false}
203
+ CONTENT --> CacheCheck
204
+ CUSTOM --> CacheCheck
205
+
206
+ CacheCheck -->|YES| CacheData[(Cache)]
207
+ CacheCheck -->|NO| GlobalData{{Global Network}}
208
+
209
+ CacheData --> Cached{Cached?}
210
+
211
+ Cached -->|NO| GlobalData
212
+ Cached -->|YES| RegisterResponse
213
+ GlobalData --> RegisterResponse
214
+
215
+ RegisterResponse[Register Response Data] --> RequestCallback{request callback?}
216
+
217
+ RequestCallback -->|YES| ExecRequestCallback[Execute Request Callback]
218
+ RequestCallback -->|NO| UnbindView
219
+ ExecRequestCallback --> UnbindView
220
+
221
+ UnbindView[Previous View: onExit & Unbind] --> BindView[New View/ViewModel: Bind]
222
+ BindView --> ViewModelInit[ViewModel: initialize]
223
+
224
+ ViewModelInit --> ViewInit[View: initialize]
225
+ ViewInit --> AddToStage[Add View to Stage]
226
+ AddToStage --> GotoViewCallback{gotoView callback?}
227
+
228
+ GotoViewCallback -->|YES| ExecGotoViewCallback[Execute gotoView Callback]
229
+ GotoViewCallback -->|NO| LoadingEndCheck
230
+ ExecGotoViewCallback --> LoadingEndCheck
231
+
232
+ LoadingEndCheck{use loading?<br/>Default: true}
233
+
234
+ LoadingEndCheck -->|YES| LoadingEnd[End Loading]
235
+ LoadingEndCheck -->|NO| OnEnter
236
+ LoadingEnd --> DisposeOverlay[Dispose Screen Overlay]
237
+ DisposeOverlay --> OnEnter
238
+
239
+ OnEnter[View: onEnter] --> StartDrawing
240
+
241
+ StartDrawing[Start Drawing] -->|Response| User
242
+
243
+ style User fill:#d5e8d4,stroke:#82b366
244
+ style StartDrawing fill:#dae8fc,stroke:#6c8ebf
245
+ style CacheData fill:#fff2cc,stroke:#d6b656
246
+ style GlobalData fill:#f5f5f5,stroke:#666666
247
+ ```
248
+
249
+ ### Main Flow Steps
250
+
251
+ | Step | Description |
252
+ |----------|------|
253
+ | **gotoView** | Entry point for screen transitions |
254
+ | **Loading** | Display/hide loading screen control |
255
+ | **Request Type** | Three types of requests: JSON, CONTENT, CUSTOM |
256
+ | **Cache** | Response data caching control |
257
+ | **View/ViewModel Bind** | New View/ViewModel binding process |
258
+ | **onEnter** | Callback after screen display completion |
259
+
260
+ ## Major Design Patterns
261
+
262
+ ### 1. MVVM (Model-View-ViewModel)
263
+
264
+ - **View**: Handles screen structure and display without business logic
265
+ - **ViewModel**: Bridges View and Model, holds UseCases and processes events
266
+ - **Model**: Manages business logic and data access
267
+
268
+ ### 2. UseCase Pattern
269
+
270
+ Create dedicated UseCase classes for each user action:
271
+
272
+ ```typescript
273
+ export class StartDragUseCase
274
+ {
275
+ execute(target: IDraggable): void
276
+ {
277
+ target.startDrag();
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### 3. Dependency Inversion
283
+
284
+ Depend on interfaces rather than concrete classes:
285
+
286
+ ```typescript
287
+ // Good example: depends on interface
288
+ import type { IDraggable } from "@/interface/IDraggable";
289
+
290
+ function startDrag(target: IDraggable): void
291
+ {
292
+ target.startDrag();
293
+ }
294
+ ```
295
+
296
+ ### 4. Repository Pattern
297
+
298
+ Abstracts data access with error handling:
299
+
300
+ ```typescript
301
+ export class HomeTextRepository
302
+ {
303
+ static async get(): Promise<IHomeTextResponse>
304
+ {
305
+ try {
306
+ const response = await fetch(`${config.api.endPoint}api/home.json`);
307
+ if (!response.ok) {
308
+ throw new Error(`HTTP error! status: ${response.status}`);
309
+ }
310
+ return await response.json();
311
+ } catch (error) {
312
+ console.error("Failed to fetch:", error);
313
+ throw error;
314
+ }
315
+ }
316
+ }
317
+ ```
318
+
319
+ ## Quick Start
320
+
321
+ ### Project Creation
322
+
323
+ ```bash
324
+ npx create-next2d-app my-app
325
+ cd my-app
326
+ npm install
327
+ npm start
328
+ ```
329
+
330
+ ### Auto-generate View/ViewModel
331
+
332
+ ```bash
333
+ npm run generate
334
+ ```
335
+
336
+ This command parses the top properties in `routing.json` and generates corresponding View and ViewModel classes.
337
+
338
+ ## Best Practices
339
+
340
+ 1. **Interface First**: Always depend on interfaces rather than concrete types
341
+ 2. **Single Responsibility Principle**: Each class should have only one responsibility
342
+ 3. **Dependency Injection**: Inject dependencies through constructors
343
+ 4. **Error Handling**: Handle errors appropriately in Repository layer
344
+ 5. **Type Safety**: Use explicit type definitions, avoid `any` type
345
+
346
+ ## Related Documentation
347
+
348
+ ### Basics
349
+ - View/ViewModel - Screen display and data binding
350
+ - Routing - URL-based screen transitions
351
+ - Configuration Files - Environment and stage configuration
352
+ - Animation Tool Integration - Leveraging Animation Tool assets
353
+
354
+ ### Next2D Player Integration
355
+ - Next2D Player - Rendering engine
356
+ - MovieClip - Timeline animation
357
+ - Event System - User interaction
358
+
359
+ ---
360
+
361
+ # AnimationTool連携
362
+
363
+ Next2D FrameworkはAnimationToolで作成したアセットとシームレスに連携できます。
364
+
365
+ ## 概要
366
+
367
+ AnimationToolは、Next2D Player用のアニメーションやUIコンポーネントを作成するためのツールです。出力されたJSONファイルをフレームワークで読み込み、MovieClipとして利用できます。
368
+
369
+ ## ディレクトリ構成
370
+
371
+ ```
372
+ src/
373
+ ├── ui/
374
+ │ ├── content/ # Animation Tool生成コンテンツ
375
+ │ │ ├── TopContent.ts
376
+ │ │ └── HomeContent.ts
377
+ │ │
378
+ │ ├── component/ # Atomic Designコンポーネント
379
+ │ │ ├── atom/ # 最小単位のコンポーネント
380
+ │ │ │ ├── ButtonAtom.ts
381
+ │ │ │ └── TextAtom.ts
382
+ │ │ ├── molecule/ # Atomを組み合わせたコンポーネント
383
+ │ │ │ ├── TopBtnMolecule.ts
384
+ │ │ │ └── HomeBtnMolecule.ts
385
+ │ │ ├── organism/ # 複数Moleculeの組み合わせ
386
+ │ │ ├── template/ # ページテンプレート
387
+ │ │ └── page/ # ページコンポーネント
388
+ │ │ ├── top/
389
+ │ │ │ └── TopPage.ts
390
+ │ │ └── home/
391
+ │ │ └── HomePage.ts
392
+ │ │
393
+ │ └── animation/ # コードアニメーション定義
394
+ │ └── top/
395
+ │ └── TopBtnShowAnimation.ts
396
+
397
+ └── file/ # Animation Tool出力ファイル
398
+ └── sample.n2d
399
+ ```
400
+
401
+ ## MovieClipContent
402
+
403
+ Animation Toolで作成したコンテンツをラップするクラスです。
404
+
405
+ ### 基本構造
406
+
407
+ ```typescript
408
+ import { MovieClipContent } from "@next2d/framework";
409
+
410
+ /**
411
+ * @see file/sample.n2d
412
+ */
413
+ export class TopContent extends MovieClipContent
414
+ {
415
+ /**
416
+ * Animation Tool上で設定したシンボル名を返す
417
+ */
418
+ get namespace(): string
419
+ {
420
+ return "TopContent";
421
+ }
422
+ }
423
+ ```
424
+
425
+ ### namespaceの役割
426
+
427
+ `namespace`プロパティは、Animation Toolで作成したシンボルの名前と一致させます。この名前を使って、読み込まれたJSONデータから対応するMovieClipが生成されます。
428
+
429
+ ## コンテンツの読み込み
430
+
431
+ ### routing.jsonでの設定
432
+
433
+ Animation ToolのJSONファイルは`routing.json`の`requests`で読み込みます。
434
+
435
+ ```json
436
+ {
437
+ "@sample": {
438
+ "requests": [
439
+ {
440
+ "type": "content",
441
+ "path": "{{ content.endPoint }}content/sample.json",
442
+ "name": "MainContent",
443
+ "cache": true
444
+ }
445
+ ]
446
+ },
447
+ "top": {
448
+ "requests": [
449
+ {
450
+ "type": "cluster",
451
+ "path": "@sample"
452
+ }
453
+ ]
454
+ }
455
+ }
456
+ ```
457
+
458
+ #### request設定
459
+
460
+ | プロパティ | 型 | 説明 |
461
+ |-----------|------|------|
462
+ | `type` | string | `"content"` を指定 |
463
+ | `path` | string | JSONファイルへのパス |
464
+ | `name` | string | レスポンスに登録されるキー名 |
465
+ | `cache` | boolean | キャッシュするかどうか |
466
+
467
+ #### cluster機能
468
+
469
+ `@`で始まるキーはクラスターとして定義され、複数のルートで共有できます。`type: "cluster"`で参照します。
470
+
471
+ ```json
472
+ {
473
+ "@common": {
474
+ "requests": [
475
+ {
476
+ "type": "content",
477
+ "path": "{{ content.endPoint }}common.json",
478
+ "name": "CommonContent",
479
+ "cache": true
480
+ }
481
+ ]
482
+ },
483
+ "top": {
484
+ "requests": [
485
+ { "type": "cluster", "path": "@common" }
486
+ ]
487
+ },
488
+ "home": {
489
+ "requests": [
490
+ { "type": "cluster", "path": "@common" }
491
+ ]
492
+ }
493
+ }
494
+ ```
495
+
496
+ ## 関連項目
497
+
498
+ - View/ViewModel
499
+ - ルーティング
500
+ - 設定ファイル
501
+
502
+ ---
503
+
504
+ # 設定ファイル
505
+
506
+ Next2D Frameworkの設定は3つのJSONファイルで管理します。
507
+
508
+ ## ファイル構成
509
+
510
+ ```
511
+ src/config/
512
+ ├── stage.json # 表示領域の設定
513
+ ├── config.json # 環境設定
514
+ └── routing.json # ルーティング設定
515
+ ```
516
+
517
+ ## stage.json
518
+
519
+ 表示領域(Stage)の設定を行うJSONファイルです。
520
+
521
+ ```json
522
+ {
523
+ "width": 1920,
524
+ "height": 1080,
525
+ "fps": 60,
526
+ "options": {
527
+ "fullScreen": true,
528
+ "tagId": null,
529
+ "bgColor": "transparent"
530
+ }
531
+ }
532
+ ```
533
+
534
+ ### プロパティ
535
+
536
+ | プロパティ | 型 | デフォルト | 説明 |
537
+ |-----------|------|----------|------|
538
+ | `width` | number | 240 | 表示領域の幅 |
539
+ | `height` | number | 240 | 表示領域の高さ |
540
+ | `fps` | number | 60 | 1秒間に何回描画するか(1〜60) |
541
+ | `options` | object | null | オプション設定 |
542
+
543
+ ### options設定
544
+
545
+ | プロパティ | 型 | デフォルト | 説明 |
546
+ |-----------|------|----------|------|
547
+ | `fullScreen` | boolean | false | Stageで設定した幅と高さを超えて画面全体に描画 |
548
+ | `tagId` | string | null | IDを指定すると、指定したIDのエレメント内で描画を行う |
549
+ | `bgColor` | string | "transparent" | 背景色を16進数で指定。デフォルトは無色透明 |
550
+
551
+ ## config.json
552
+
553
+ 環境ごとの設定を管理するファイルです。`local`、`dev`、`stg`、`prd`、`all`と区切られており、`all`以外は任意の環境名です。
554
+
555
+ ```json
556
+ {
557
+ "local": {
558
+ "api": {
559
+ "endPoint": "http://localhost:3000/"
560
+ },
561
+ "content": {
562
+ "endPoint": "http://localhost:5500/"
563
+ }
564
+ },
565
+ "dev": {
566
+ "api": {
567
+ "endPoint": "https://dev-api.example.com/"
568
+ }
569
+ },
570
+ "prd": {
571
+ "api": {
572
+ "endPoint": "https://api.example.com/"
573
+ }
574
+ },
575
+ "all": {
576
+ "spa": true,
577
+ "defaultTop": "top",
578
+ "loading": {
579
+ "callback": "Loading"
580
+ },
581
+ "gotoView": {
582
+ "callback": ["callback.Background"]
583
+ }
584
+ }
585
+ }
586
+ ```
587
+
588
+ ### all設定
589
+
590
+ `all`はどの環境でも書き出される共通変数です。
591
+
592
+ | プロパティ | 型 | デフォルト | 説明 |
593
+ |-----------|------|----------|------|
594
+ | `spa` | boolean | true | Single Page ApplicationとしてURLでシーンを制御 |
595
+ | `defaultTop` | string | "top" | ページトップのView。設定がない場合はTopViewクラスが起動 |
596
+ | `loading.callback` | string | Loading | ローディング画面のクラス名。start関数とend関数を呼び出す |
597
+ | `gotoView.callback` | string \| array | ["callback.Background"] | gotoView完了後のコールバッククラス |
598
+
599
+ ### platform設定
600
+
601
+ ビルド時の`--platform`で指定した値がセットされます。
602
+
603
+ 対応値: `macos`, `windows`, `linux`, `ios`, `android`, `web`
604
+
605
+ ```typescript
606
+ import { config } from "@/config/Config";
607
+
608
+ if (config.platform === "ios") {
609
+ // iOS固有の処理
610
+ }
611
+ ```
612
+
613
+ ## routing.json
614
+
615
+ ルーティングの設定ファイルです。詳細は[ルーティング](#ルーティング)を参照してください。
616
+
617
+ ```json
618
+ {
619
+ "top": {
620
+ "requests": [
621
+ {
622
+ "type": "json",
623
+ "path": "{{api.endPoint}}api/top.json",
624
+ "name": "TopText"
625
+ }
626
+ ]
627
+ },
628
+ "home": {
629
+ "requests": []
630
+ }
631
+ }
632
+ ```
633
+
634
+ ## 設定値の取得
635
+
636
+ コード内で設定値を取得するには`config`オブジェクトを使用します。
637
+
638
+ ### Config.tsの例
639
+
640
+ ```typescript
641
+ import stageJson from "./stage.json";
642
+ import configJson from "./config.json";
643
+
644
+ interface IStageConfig {
645
+ width: number;
646
+ height: number;
647
+ fps: number;
648
+ options: {
649
+ fullScreen: boolean;
650
+ tagId: string | null;
651
+ bgColor: string;
652
+ };
653
+ }
654
+
655
+ interface IConfig {
656
+ stage: IStageConfig;
657
+ api: {
658
+ endPoint: string;
659
+ };
660
+ content: {
661
+ endPoint: string;
662
+ };
663
+ spa: boolean;
664
+ defaultTop: string;
665
+ platform: string;
666
+ }
667
+
668
+ export const config: IConfig = {
669
+ stage: stageJson,
670
+ ...configJson
671
+ };
672
+ ```
673
+
674
+ ### 使用例
675
+
676
+ ```typescript
677
+ import { config } from "@/config/Config";
678
+
679
+ // ステージ設定
680
+ const stageWidth = config.stage.width;
681
+ const stageHeight = config.stage.height;
682
+
683
+ // API設定
684
+ const apiEndPoint = config.api.endPoint;
685
+
686
+ // SPA設定
687
+ const isSpa = config.spa;
688
+ ```
689
+
690
+ ## ローディング画面
691
+
692
+ `loading.callback`で設定したクラスの`start`関数と`end`関数が呼び出されます。
693
+
694
+ ```typescript
695
+ export class Loading
696
+ {
697
+ private shape: Shape;
698
+
699
+ constructor()
700
+ {
701
+ this.shape = new Shape();
702
+ // ローディング表示の初期化
703
+ }
704
+
705
+ start(): void
706
+ {
707
+ // ローディング開始時の処理
708
+ stage.addChild(this.shape);
709
+ }
710
+
711
+ end(): void
712
+ {
713
+ // ローディング終了時の処理
714
+ this.shape.remove();
715
+ }
716
+ }
717
+ ```
718
+
719
+ ## gotoViewコールバック
720
+
721
+ `gotoView.callback`で設定したクラスの`execute`関数が呼び出されます。複数のクラスを配列で設定でき、async/awaitで順次実行されます。
722
+
723
+ ```typescript
724
+ import { app } from "@next2d/framework";
725
+ import { Shape, stage } from "@next2d/display";
726
+
727
+ export class Background
728
+ {
729
+ public readonly shape: Shape;
730
+
731
+ constructor()
732
+ {
733
+ this.shape = new Shape();
734
+ }
735
+
736
+ execute(): void
737
+ {
738
+ const context = app.getContext();
739
+ const view = context.view;
740
+ if (!view) return;
741
+
742
+ // 背景を最背面に配置
743
+ view.addChildAt(this.shape, 0);
744
+ }
745
+ }
746
+ ```
747
+
748
+ ## ビルドコマンド
749
+
750
+ 環境を指定してビルド:
751
+
752
+ ```bash
753
+ # ローカル環境
754
+ npm run build -- --env=local
755
+
756
+ # 開発環境
757
+ npm run build -- --env=dev
758
+
759
+ # 本番環境
760
+ npm run build -- --env=prd
761
+ ```
762
+
763
+ プラットフォームを指定:
764
+
765
+ ```bash
766
+ npm run build -- --platform=web
767
+ npm run build -- --platform=ios
768
+ npm run build -- --platform=android
769
+ ```
770
+
771
+ ## 設定例
772
+
773
+ ### 完全な設定ファイルの例
774
+
775
+ #### stage.json
776
+
777
+ ```json
778
+ {
779
+ "width": 1920,
780
+ "height": 1080,
781
+ "fps": 60,
782
+ "options": {
783
+ "fullScreen": true,
784
+ "tagId": null,
785
+ "bgColor": "#1461A0"
786
+ }
787
+ }
788
+ ```
789
+
790
+ #### config.json
791
+
792
+ ```json
793
+ {
794
+ "local": {
795
+ "api": {
796
+ "endPoint": "http://localhost:3000/"
797
+ },
798
+ "content": {
799
+ "endPoint": "http://localhost:5500/mock/content/"
800
+ }
801
+ },
802
+ "dev": {
803
+ "api": {
804
+ "endPoint": "https://dev-api.example.com/"
805
+ },
806
+ "content": {
807
+ "endPoint": "https://dev-cdn.example.com/content/"
808
+ }
809
+ },
810
+ "prd": {
811
+ "api": {
812
+ "endPoint": "https://api.example.com/"
813
+ },
814
+ "content": {
815
+ "endPoint": "https://cdn.example.com/content/"
816
+ }
817
+ },
818
+ "all": {
819
+ "spa": true,
820
+ "defaultTop": "top",
821
+ "loading": {
822
+ "callback": "Loading"
823
+ },
824
+ "gotoView": {
825
+ "callback": ["callback.Background"]
826
+ }
827
+ }
828
+ }
829
+ ```
830
+
831
+ ## 関連項目
832
+
833
+ - [ルーティング](#ルーティング)
834
+ - [View/ViewModel](#view-と-viewmodel)
835
+
836
+ ---
837
+
838
+ # ルーティング
839
+
840
+ Next2D FrameworkはシングルページアプリケーションとしてURLでシーンを制御できます。ルーティングは`routing.json`で設定します。
841
+
842
+ ## 基本設定
843
+
844
+ ルーティングのトッププロパティは英数字とスラッシュが使用できます。スラッシュをキーにCamelCaseでViewクラスにアクセスします。
845
+
846
+ ```json
847
+ {
848
+ "top": {
849
+ "requests": []
850
+ },
851
+ "home": {
852
+ "requests": []
853
+ },
854
+ "quest/list": {
855
+ "requests": []
856
+ }
857
+ }
858
+ ```
859
+
860
+ 上記の場合:
861
+ - `top` → `TopView`クラス
862
+ - `home` → `HomeView`クラス
863
+ - `quest/list` → `QuestListView`クラス
864
+
865
+ ## ルート定義
866
+
867
+ ### 基本的なルート
868
+
869
+ ```json
870
+ {
871
+ "top": {
872
+ "requests": []
873
+ }
874
+ }
875
+ ```
876
+
877
+ アクセス: `https://example.com/` または `https://example.com/top`
878
+
879
+ ### セカンドレベルプロパティ
880
+
881
+ | プロパティ | 型 | デフォルト | 説明 |
882
+ |-----------|------|----------|------|
883
+ | `private` | boolean | false | URLでの直接アクセスを制御。trueの場合、URLでアクセスするとTopViewが読み込まれる |
884
+ | `requests` | array | null | Viewがbindされる前にリクエストを送信 |
885
+
886
+ ### プライベートルート
887
+
888
+ URLでの直接アクセスを禁止したい場合:
889
+
890
+ ```json
891
+ {
892
+ "quest/detail": {
893
+ "private": true,
894
+ "requests": []
895
+ }
896
+ }
897
+ ```
898
+
899
+ `private: true`の場合、URLで直接アクセスすると`TopView`にリダイレクトされます。プログラムからの`app.gotoView()`でのみアクセス可能です。
900
+
901
+ ## requestsの設定
902
+
903
+ Viewがbindされる前にデータを取得できます。取得したデータは`app.getResponse()`で取得できます。
904
+
905
+ ### requests配列の設定項目
906
+
907
+ | プロパティ | 型 | デフォルト | 説明 |
908
+ |-----------|------|----------|------|
909
+ | `type` | string | content | `json`、`content`、`custom`の固定値 |
910
+ | `path` | string | empty | リクエスト先のパス |
911
+ | `name` | string | empty | `response`にセットするキー名 |
912
+ | `cache` | boolean | false | データをキャッシュするか |
913
+ | `callback` | string \| array | null | リクエスト完了後のコールバッククラス |
914
+ | `class` | string | empty | リクエストを実行するクラス(typeがcustomの場合のみ) |
915
+ | `access` | string | public | 関数へのアクセス修飾子(`public`または`static`) |
916
+ | `method` | string | empty | 実行する関数名(typeがcustomの場合のみ) |
917
+
918
+ ### typeの種類
919
+
920
+ #### json
921
+
922
+ 外部JSONデータを取得:
923
+
924
+ ```json
925
+ {
926
+ "home": {
927
+ "requests": [
928
+ {
929
+ "type": "json",
930
+ "path": "{{api.endPoint}}api/home.json",
931
+ "name": "HomeData"
932
+ }
933
+ ]
934
+ }
935
+ }
936
+ ```
937
+
938
+ #### content
939
+
940
+ Animation ToolのJSONを取得:
941
+
942
+ ```json
943
+ {
944
+ "top": {
945
+ "requests": [
946
+ {
947
+ "type": "content",
948
+ "path": "{{content.endPoint}}top.json",
949
+ "name": "TopContent"
950
+ }
951
+ ]
952
+ }
953
+ }
954
+ ```
955
+
956
+ #### custom
957
+
958
+ カスタムクラスでリクエストを実行:
959
+
960
+ ```json
961
+ {
962
+ "user/profile": {
963
+ "requests": [
964
+ {
965
+ "type": "custom",
966
+ "class": "repository.UserRepository",
967
+ "access": "static",
968
+ "method": "getProfile",
969
+ "name": "UserProfile"
970
+ }
971
+ ]
972
+ }
973
+ }
974
+ ```
975
+
976
+ ### 変数の展開
977
+
978
+ `{{***}}`で囲むと`config.json`の変数を取得できます:
979
+
980
+ ```json
981
+ {
982
+ "path": "{{api.endPoint}}path/to/api"
983
+ }
984
+ ```
985
+
986
+ ### キャッシュの利用
987
+
988
+ `cache: true`を設定すると、データがキャッシュされます。キャッシュしたデータは画面遷移しても初期化されません。
989
+
990
+ ```json
991
+ {
992
+ "top": {
993
+ "requests": [
994
+ {
995
+ "type": "json",
996
+ "path": "{{api.endPoint}}api/master.json",
997
+ "name": "MasterData",
998
+ "cache": true
999
+ }
1000
+ ]
1001
+ }
1002
+ }
1003
+ ```
1004
+
1005
+ キャッシュデータの取得:
1006
+
1007
+ ```typescript
1008
+ import { app } from "@next2d/framework";
1009
+
1010
+ const cache = app.getCache();
1011
+ if (cache.has("MasterData")) {
1012
+ const masterData = cache.get("MasterData");
1013
+ }
1014
+ ```
1015
+
1016
+ ### コールバック
1017
+
1018
+ リクエスト完了後にコールバックを実行:
1019
+
1020
+ ```json
1021
+ {
1022
+ "home": {
1023
+ "requests": [
1024
+ {
1025
+ "type": "json",
1026
+ "path": "{{api.endPoint}}api/home.json",
1027
+ "name": "HomeData",
1028
+ "callback": "callback.HomeDataCallback"
1029
+ }
1030
+ ]
1031
+ }
1032
+ }
1033
+ ```
1034
+
1035
+ コールバッククラス:
1036
+
1037
+ ```typescript
1038
+ export class HomeDataCallback
1039
+ {
1040
+ constructor(data: any)
1041
+ {
1042
+ // 取得したデータが渡される
1043
+ }
1044
+
1045
+ execute(): void
1046
+ {
1047
+ // コールバック処理
1048
+ }
1049
+ }
1050
+ ```
1051
+
1052
+ ## 画面遷移
1053
+
1054
+ ### app.gotoView()
1055
+
1056
+ `app.gotoView()`で画面遷移を行います:
1057
+
1058
+ ```typescript
1059
+ import { app } from "@next2d/framework";
1060
+
1061
+ // 基本的な遷移
1062
+ await app.gotoView("home");
1063
+
1064
+ // パスで遷移
1065
+ await app.gotoView("quest/list");
1066
+
1067
+ // クエリパラメータ付き
1068
+ await app.gotoView("quest/detail?id=123");
1069
+ ```
1070
+
1071
+ ### UseCaseでの画面遷移
1072
+
1073
+ 画面遷移はUseCaseで行うことを推奨します:
1074
+
1075
+ ```typescript
1076
+ import { app } from "@next2d/framework";
1077
+
1078
+ export class NavigateToViewUseCase
1079
+ {
1080
+ async execute(viewName: string): Promise<void>
1081
+ {
1082
+ await app.gotoView(viewName);
1083
+ }
1084
+ }
1085
+ ```
1086
+
1087
+ ViewModelでの使用:
1088
+
1089
+ ```typescript
1090
+ export class TopViewModel extends ViewModel
1091
+ {
1092
+ private readonly navigateToViewUseCase: NavigateToViewUseCase;
1093
+
1094
+ constructor()
1095
+ {
1096
+ super();
1097
+ this.navigateToViewUseCase = new NavigateToViewUseCase();
1098
+ }
1099
+
1100
+ async onClickStartButton(): Promise<void>
1101
+ {
1102
+ await this.navigateToViewUseCase.execute("home");
1103
+ }
1104
+ }
1105
+ ```
1106
+
1107
+ ## レスポンスデータの取得
1108
+
1109
+ `requests`で取得したデータは`app.getResponse()`で取得できます:
1110
+
1111
+ ```typescript
1112
+ import { app } from "@next2d/framework";
1113
+
1114
+ async initialize(): Promise<void>
1115
+ {
1116
+ const response = app.getResponse();
1117
+
1118
+ if (response.has("TopText")) {
1119
+ const topText = response.get("TopText") as { word: string };
1120
+ this.text = topText.word;
1121
+ }
1122
+ }
1123
+ ```
1124
+
1125
+ **注意:** `response`データは画面遷移すると初期化されます。画面を跨いで保持したいデータは`cache: true`を設定してください。
1126
+
1127
+ ## SPAモード
1128
+
1129
+ `config.json`の`all.spa`で設定します:
1130
+
1131
+ ```json
1132
+ {
1133
+ "all": {
1134
+ "spa": true
1135
+ }
1136
+ }
1137
+ ```
1138
+
1139
+ - `true`: URLでシーンを制御(History API使用)
1140
+ - `false`: URLによるシーン制御を無効化
1141
+
1142
+ ## デフォルトのトップページ
1143
+
1144
+ `config.json`で設定:
1145
+
1146
+ ```json
1147
+ {
1148
+ "all": {
1149
+ "defaultTop": "top"
1150
+ }
1151
+ }
1152
+ ```
1153
+
1154
+ 設定がない場合は`TopView`クラスが起動します。
1155
+
1156
+ ## View/ViewModelの自動生成
1157
+
1158
+ `routing.json`の設定から自動生成できます:
1159
+
1160
+ ```bash
1161
+ npm run generate
1162
+ ```
1163
+
1164
+ このコマンドは`routing.json`のトッププロパティを解析し、対応するViewとViewModelクラスを生成します。
1165
+
1166
+ ## 設定例
1167
+
1168
+ ### 完全な routing.json の例
1169
+
1170
+ ```json
1171
+ {
1172
+ "top": {
1173
+ "requests": [
1174
+ {
1175
+ "type": "json",
1176
+ "path": "{{api.endPoint}}api/top.json",
1177
+ "name": "TopText"
1178
+ }
1179
+ ]
1180
+ },
1181
+ "home": {
1182
+ "requests": [
1183
+ {
1184
+ "type": "json",
1185
+ "path": "{{api.endPoint}}api/home.json",
1186
+ "name": "HomeData"
1187
+ },
1188
+ {
1189
+ "type": "content",
1190
+ "path": "{{content.endPoint}}home.json",
1191
+ "name": "HomeContent",
1192
+ "cache": true
1193
+ }
1194
+ ]
1195
+ },
1196
+ "quest/list": {
1197
+ "requests": [
1198
+ {
1199
+ "type": "custom",
1200
+ "class": "repository.QuestRepository",
1201
+ "access": "static",
1202
+ "method": "getList",
1203
+ "name": "QuestList"
1204
+ }
1205
+ ]
1206
+ },
1207
+ "quest/detail": {
1208
+ "private": true,
1209
+ "requests": [
1210
+ {
1211
+ "type": "custom",
1212
+ "class": "repository.QuestRepository",
1213
+ "access": "static",
1214
+ "method": "getDetail",
1215
+ "name": "QuestDetail"
1216
+ }
1217
+ ]
1218
+ }
1219
+ }
1220
+ ```
1221
+
1222
+ ## 関連項目
1223
+
1224
+ - [View/ViewModel](#view-と-viewmodel)
1225
+ - [設定ファイル](#設定ファイル)
1226
+
1227
+ ---
1228
+
1229
+ # View と ViewModel
1230
+
1231
+ Next2D FrameworkはMVVM(Model-View-ViewModel)パターンを採用しています。1画面にViewとViewModelをワンセット作成するのが基本スタイルです。
1232
+
1233
+ ## アーキテクチャ
1234
+
1235
+ ```mermaid
1236
+ graph TB
1237
+ subgraph ViewLayer["View Layer"]
1238
+ ViewRole["画面の構造と表示を担当"]
1239
+ ViewRule["ビジネスロジックは持たない"]
1240
+ end
1241
+
1242
+ subgraph ViewModelLayer["ViewModel Layer"]
1243
+ VMRole1["ViewとModelの橋渡し"]
1244
+ VMRole2["UseCaseを保持"]
1245
+ VMRole3["イベントハンドリング"]
1246
+ end
1247
+
1248
+ subgraph ModelLayer["Model Layer"]
1249
+ ModelRole1["ビジネスロジック(UseCase)"]
1250
+ ModelRole2["データアクセス(Repository)"]
1251
+ end
1252
+
1253
+ ViewLayer <-->|双方向| ViewModelLayer
1254
+ ViewModelLayer <--> ModelLayer
1255
+ ```
1256
+
1257
+ ## ディレクトリ構造
1258
+
1259
+ ```
1260
+ src/
1261
+ └── view/
1262
+ ├── top/
1263
+ │ ├── TopView.ts
1264
+ │ └── TopViewModel.ts
1265
+ └── home/
1266
+ ├── HomeView.ts
1267
+ └── HomeViewModel.ts
1268
+ ```
1269
+
1270
+ ## View
1271
+
1272
+ Viewはメインコンテキストにアタッチされるコンテナです。Viewは表示構造のみを担当し、ビジネスロジックはViewModelに委譲します。
1273
+
1274
+ ### Viewの責務
1275
+
1276
+ - **画面の構造定義** - UIコンポーネントの配置と座標設定
1277
+ - **イベントリスナーの登録** - ViewModelのメソッドと接続
1278
+ - **ライフサイクル管理** - `initialize`, `onEnter`, `onExit`
1279
+
1280
+ ### 基本構造
1281
+
1282
+ ```typescript
1283
+ import type { TopViewModel } from "./TopViewModel";
1284
+ import { View } from "@next2d/framework";
1285
+ import { TopPage } from "@/ui/component/page/top/TopPage";
1286
+
1287
+ export class TopView extends View<TopViewModel>
1288
+ {
1289
+ private readonly _topPage: TopPage;
1290
+
1291
+ constructor(vm: TopViewModel)
1292
+ {
1293
+ super(vm);
1294
+ this._topPage = new TopPage();
1295
+ this.addChild(this._topPage);
1296
+ }
1297
+
1298
+ async initialize(): Promise<void>
1299
+ {
1300
+ this._topPage.initialize(this.vm);
1301
+ }
1302
+
1303
+ async onEnter(): Promise<void>
1304
+ {
1305
+ await this._topPage.onEnter();
1306
+ }
1307
+
1308
+ async onExit(): Promise<void>
1309
+ {
1310
+ return void 0;
1311
+ }
1312
+ }
1313
+ ```
1314
+
1315
+ ### ライフサイクル
1316
+
1317
+ ```mermaid
1318
+ sequenceDiagram
1319
+ participant Framework as Framework
1320
+ participant VM as ViewModel
1321
+ participant View as View
1322
+ participant UI as UI Components
1323
+
1324
+ Note over Framework,UI: 画面遷移開始
1325
+
1326
+ Framework->>VM: new ViewModel()
1327
+ Framework->>VM: initialize()
1328
+ Note over VM: ViewModelが先に初期化される
1329
+
1330
+ Framework->>View: new View(vm)
1331
+ Framework->>View: initialize()
1332
+ View->>UI: コンポーネント作成
1333
+ View->>VM: イベントリスナー登録
1334
+
1335
+ Framework->>View: onEnter()
1336
+ View->>UI: アニメーション開始
1337
+
1338
+ Note over Framework,UI: ユーザーが画面を操作
1339
+
1340
+ Framework->>View: onExit()
1341
+ View->>UI: クリーンアップ
1342
+ ```
1343
+
1344
+ #### initialize() - 初期化
1345
+
1346
+ **呼び出しタイミング:**
1347
+ - Viewのインスタンスが生成された直後
1348
+ - 画面遷移時に1回だけ呼び出される
1349
+ - ViewModelの`initialize()`より**後**に実行される
1350
+
1351
+ **主な用途:**
1352
+ - UIコンポーネントの生成と配置
1353
+ - イベントリスナーの登録
1354
+ - 子要素の追加(`addChild`)
1355
+
1356
+ ```typescript
1357
+ async initialize(): Promise<void>
1358
+ {
1359
+ const { HomeBtnMolecule } = await import("@/ui/component/molecule/HomeBtnMolecule");
1360
+ const { PointerEvent } = next2d.events;
1361
+
1362
+ const homeContent = new HomeBtnMolecule();
1363
+ homeContent.x = 120;
1364
+ homeContent.y = 120;
1365
+
1366
+ // イベントをViewModelに委譲
1367
+ homeContent.addEventListener(
1368
+ PointerEvent.POINTER_DOWN,
1369
+ this.vm.homeContentPointerDownEvent
1370
+ );
1371
+
1372
+ this.addChild(homeContent);
1373
+ }
1374
+ ```
1375
+
1376
+ #### onEnter() - 画面表示時
1377
+
1378
+ **呼び出しタイミング:**
1379
+ - `initialize()`の実行完了後
1380
+ - 画面が表示される直前
1381
+
1382
+ **主な用途:**
1383
+ - 入場アニメーションの開始
1384
+ - タイマーやインターバルの開始
1385
+ - フォーカス設定
1386
+
1387
+ ```typescript
1388
+ async onEnter(): Promise<void>
1389
+ {
1390
+ const topBtn = this.getChildByName("topBtn") as TopBtnMolecule;
1391
+ topBtn.playEntrance(() => {
1392
+ console.log("アニメーション完了");
1393
+ });
1394
+ }
1395
+ ```
1396
+
1397
+ #### onExit() - 画面非表示時
1398
+
1399
+ **呼び出しタイミング:**
1400
+ - 別の画面に遷移する直前
1401
+ - Viewが破棄される前
1402
+
1403
+ **主な用途:**
1404
+ - アニメーションの停止
1405
+ - タイマーやインターバルのクリア
1406
+ - リソースの解放
1407
+
1408
+ ```typescript
1409
+ async onExit(): Promise<void>
1410
+ {
1411
+ if (this.autoSlideTimer) {
1412
+ clearInterval(this.autoSlideTimer);
1413
+ this.autoSlideTimer = null;
1414
+ }
1415
+ }
1416
+ ```
1417
+
1418
+ ## ViewModel
1419
+
1420
+ ViewModelはViewとModelの橋渡しを行います。UseCaseを保持し、Viewからのイベントを処理してビジネスロジックを実行します。
1421
+
1422
+ ### ViewModelの責務
1423
+
1424
+ - **イベント処理** - Viewからのイベントを受け取る
1425
+ - **UseCaseの実行** - ビジネスロジックを呼び出す
1426
+ - **依存性の管理** - UseCaseのインスタンスを保持
1427
+ - **状態管理** - 画面固有の状態を管理
1428
+
1429
+ ### 基本構造
1430
+
1431
+ ```typescript
1432
+ import { ViewModel, app } from "@next2d/framework";
1433
+ import { NavigateToViewUseCase } from "@/model/application/top/usecase/NavigateToViewUseCase";
1434
+
1435
+ export class TopViewModel extends ViewModel
1436
+ {
1437
+ private readonly navigateToViewUseCase: NavigateToViewUseCase;
1438
+ private topText: string = "";
1439
+
1440
+ constructor()
1441
+ {
1442
+ super();
1443
+ this.navigateToViewUseCase = new NavigateToViewUseCase();
1444
+ }
1445
+
1446
+ async initialize(): Promise<void>
1447
+ {
1448
+ // routing.jsonのrequestsで取得したデータを受け取る
1449
+ const response = app.getResponse();
1450
+ this.topText = response.has("TopText")
1451
+ ? (response.get("TopText") as { word: string }).word
1452
+ : "";
1453
+ }
1454
+
1455
+ getTopText(): string
1456
+ {
1457
+ return this.topText;
1458
+ }
1459
+
1460
+ async onClickStartButton(): Promise<void>
1461
+ {
1462
+ await this.navigateToViewUseCase.execute("home");
1463
+ }
1464
+ }
1465
+ ```
1466
+
1467
+ ### ViewModelの初期化タイミング
1468
+
1469
+ **重要: ViewModelの`initialize()`はViewの`initialize()`より前に呼び出されます。**
1470
+
1471
+ ```
1472
+ 1. ViewModel のインスタンス生成
1473
+
1474
+ 2. ViewModel.initialize() ← ViewModelが先
1475
+
1476
+ 3. View のインスタンス生成(ViewModelを注入)
1477
+
1478
+ 4. View.initialize()
1479
+
1480
+ 5. View.onEnter()
1481
+ ```
1482
+
1483
+ これにより、Viewの初期化時にはViewModelのデータが既に準備されています。
1484
+
1485
+ ```typescript
1486
+ // HomeViewModel.ts
1487
+ export class HomeViewModel extends ViewModel
1488
+ {
1489
+ private homeText: string = "";
1490
+
1491
+ async initialize(): Promise<void>
1492
+ {
1493
+ // ViewModelのinitializeで事前にデータ取得
1494
+ const data = await HomeTextRepository.get();
1495
+ this.homeText = data.word;
1496
+ }
1497
+
1498
+ getHomeText(): string
1499
+ {
1500
+ return this.homeText;
1501
+ }
1502
+ }
1503
+
1504
+ // HomeView.ts
1505
+ export class HomeView extends View<HomeViewModel>
1506
+ {
1507
+ constructor(private readonly vm: HomeViewModel)
1508
+ {
1509
+ super();
1510
+ }
1511
+
1512
+ async initialize(): Promise<void>
1513
+ {
1514
+ // この時点でvm.initialize()は既に完了している
1515
+ const text = this.vm.getHomeText();
1516
+
1517
+ // 取得済みのデータを使ってUIを構築
1518
+ const textField = new TextAtom(text);
1519
+ this.addChild(textField);
1520
+ }
1521
+ }
1522
+ ```
1523
+
1524
+ ## 画面遷移
1525
+
1526
+ 画面遷移には`app.gotoView()`を使用します。
1527
+
1528
+ ```typescript
1529
+ import { app } from "@next2d/framework";
1530
+
1531
+ // 指定のViewに遷移
1532
+ await app.gotoView("home");
1533
+
1534
+ // パラメータ付きで遷移
1535
+ await app.gotoView("user/detail?id=123");
1536
+ ```
1537
+
1538
+ ### UseCaseでの画面遷移
1539
+
1540
+ ```typescript
1541
+ import { app } from "@next2d/framework";
1542
+
1543
+ export class NavigateToViewUseCase
1544
+ {
1545
+ async execute(viewName: string): Promise<void>
1546
+ {
1547
+ await app.gotoView(viewName);
1548
+ }
1549
+ }
1550
+ ```
1551
+
1552
+ ## レスポンスデータの取得
1553
+
1554
+ `routing.json`で設定した`requests`のデータは`app.getResponse()`で取得できます。
1555
+
1556
+ ```typescript
1557
+ import { app } from "@next2d/framework";
1558
+
1559
+ async initialize(): Promise<void>
1560
+ {
1561
+ const response = app.getResponse();
1562
+
1563
+ if (response.has("UserData")) {
1564
+ const userData = response.get("UserData");
1565
+ this.userName = userData.name;
1566
+ }
1567
+ }
1568
+ ```
1569
+
1570
+ ## キャッシュデータの取得
1571
+
1572
+ `cache: true`を設定したデータは`app.getCache()`で取得できます。
1573
+
1574
+ ```typescript
1575
+ import { app } from "@next2d/framework";
1576
+
1577
+ const cache = app.getCache();
1578
+ if (cache.has("MasterData")) {
1579
+ const masterData = cache.get("MasterData");
1580
+ }
1581
+ ```
1582
+
1583
+ ## 設計原則
1584
+
1585
+ ### 1. 関心の分離
1586
+
1587
+ ```typescript
1588
+ // 良い例: Viewは表示のみ、ViewModelはロジック
1589
+ class HomeView extends View<HomeViewModel>
1590
+ {
1591
+ async initialize(): Promise<void>
1592
+ {
1593
+ const btn = new HomeBtnMolecule();
1594
+ btn.addEventListener(PointerEvent.POINTER_DOWN, this.vm.onClick);
1595
+ }
1596
+ }
1597
+
1598
+ class HomeViewModel extends ViewModel
1599
+ {
1600
+ onClick(event: PointerEvent): void
1601
+ {
1602
+ this.someUseCase.execute();
1603
+ }
1604
+ }
1605
+ ```
1606
+
1607
+ ### 2. 依存性の逆転
1608
+
1609
+ ViewModelはインターフェースに依存し、具象クラスに依存しません。
1610
+
1611
+ ```typescript
1612
+ // 良い例: インターフェースに依存
1613
+ homeContentPointerDownEvent(event: PointerEvent): void
1614
+ {
1615
+ const target = event.currentTarget as unknown as IDraggable;
1616
+ this.startDragUseCase.execute(target);
1617
+ }
1618
+ ```
1619
+
1620
+ ### 3. イベントは必ずViewModelに委譲
1621
+
1622
+ View内でイベント処理を完結させず、必ずViewModelに委譲します。
1623
+
1624
+ ## View/ViewModel作成のテンプレート
1625
+
1626
+ ### View
1627
+
1628
+ ```typescript
1629
+ import type { YourViewModel } from "./YourViewModel";
1630
+ import { View } from "@next2d/framework";
1631
+
1632
+ export class YourView extends View<YourViewModel>
1633
+ {
1634
+ constructor(vm: YourViewModel)
1635
+ {
1636
+ super(vm);
1637
+ }
1638
+
1639
+ async initialize(): Promise<void>
1640
+ {
1641
+ // UIコンポーネントの作成と配置
1642
+ }
1643
+
1644
+ async onEnter(): Promise<void>
1645
+ {
1646
+ // 画面表示時の処理
1647
+ }
1648
+
1649
+ async onExit(): Promise<void>
1650
+ {
1651
+ // 画面非表示時の処理
1652
+ }
1653
+ }
1654
+ ```
1655
+
1656
+ ### ViewModel
1657
+
1658
+ ```typescript
1659
+ import { ViewModel } from "@next2d/framework";
1660
+ import { YourUseCase } from "@/model/application/your/usecase/YourUseCase";
1661
+
1662
+ export class YourViewModel extends ViewModel
1663
+ {
1664
+ private readonly yourUseCase: YourUseCase;
1665
+
1666
+ constructor()
1667
+ {
1668
+ super();
1669
+ this.yourUseCase = new YourUseCase();
1670
+ }
1671
+
1672
+ async initialize(): Promise<void>
1673
+ {
1674
+ return void 0;
1675
+ }
1676
+
1677
+ yourEventHandler(event: Event): void
1678
+ {
1679
+ this.yourUseCase.execute();
1680
+ }
1681
+ }
1682
+ ```
1683
+
1684
+ ## 関連項目
1685
+
1686
+ - [ルーティング](#ルーティング)
1687
+ - [設定ファイル](#設定ファイル)