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.
- package/README.md +344 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +211 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/prompts.test.d.ts +2 -0
- package/dist/prompts/prompts.test.d.ts.map +1 -0
- package/dist/prompts/prompts.test.js +23 -0
- package/dist/prompts/prompts.test.js.map +1 -0
- package/dist/references/develop-specs.md +1576 -0
- package/dist/references/framework-specs.md +1687 -0
- package/dist/references/player-specs.md +3292 -0
- package/dist/resources/index.d.ts +3 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +185 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/resources.test.d.ts +2 -0
- package/dist/resources/resources.test.d.ts.map +1 -0
- package/dist/resources/resources.test.js +32 -0
- package/dist/resources/resources.test.js.map +1 -0
- package/dist/templates/animation.d.ts +6 -0
- package/dist/templates/animation.d.ts.map +1 -0
- package/dist/templates/animation.js +65 -0
- package/dist/templates/animation.js.map +1 -0
- package/dist/templates/animation.test.d.ts +2 -0
- package/dist/templates/animation.test.d.ts.map +1 -0
- package/dist/templates/animation.test.js +30 -0
- package/dist/templates/animation.test.js.map +1 -0
- package/dist/templates/domainService.d.ts +9 -0
- package/dist/templates/domainService.d.ts.map +1 -0
- package/dist/templates/domainService.js +56 -0
- package/dist/templates/domainService.js.map +1 -0
- package/dist/templates/domainService.test.d.ts +2 -0
- package/dist/templates/domainService.test.d.ts.map +1 -0
- package/dist/templates/domainService.test.js +33 -0
- package/dist/templates/domainService.test.js.map +1 -0
- package/dist/templates/interfaceFile.d.ts +5 -0
- package/dist/templates/interfaceFile.d.ts.map +1 -0
- package/dist/templates/interfaceFile.js +16 -0
- package/dist/templates/interfaceFile.js.map +1 -0
- package/dist/templates/interfaceFile.test.d.ts +2 -0
- package/dist/templates/interfaceFile.test.d.ts.map +1 -0
- package/dist/templates/interfaceFile.test.js +30 -0
- package/dist/templates/interfaceFile.test.js.map +1 -0
- package/dist/templates/loading.d.ts +5 -0
- package/dist/templates/loading.d.ts.map +1 -0
- package/dist/templates/loading.js +62 -0
- package/dist/templates/loading.js.map +1 -0
- package/dist/templates/loading.test.d.ts +2 -0
- package/dist/templates/loading.test.d.ts.map +1 -0
- package/dist/templates/loading.test.js +31 -0
- package/dist/templates/loading.test.js.map +1 -0
- package/dist/templates/repository.d.ts +2 -0
- package/dist/templates/repository.d.ts.map +1 -0
- package/dist/templates/repository.js +42 -0
- package/dist/templates/repository.js.map +1 -0
- package/dist/templates/repository.test.d.ts +2 -0
- package/dist/templates/repository.test.d.ts.map +1 -0
- package/dist/templates/repository.test.js +44 -0
- package/dist/templates/repository.test.js.map +1 -0
- package/dist/templates/uiComponent.d.ts +4 -0
- package/dist/templates/uiComponent.d.ts.map +1 -0
- package/dist/templates/uiComponent.js +108 -0
- package/dist/templates/uiComponent.js.map +1 -0
- package/dist/templates/uiComponent.test.d.ts +2 -0
- package/dist/templates/uiComponent.test.d.ts.map +1 -0
- package/dist/templates/uiComponent.test.js +76 -0
- package/dist/templates/uiComponent.test.js.map +1 -0
- package/dist/templates/usecase.d.ts +2 -0
- package/dist/templates/usecase.d.ts.map +1 -0
- package/dist/templates/usecase.js +31 -0
- package/dist/templates/usecase.js.map +1 -0
- package/dist/templates/usecase.test.d.ts +2 -0
- package/dist/templates/usecase.test.d.ts.map +1 -0
- package/dist/templates/usecase.test.js +23 -0
- package/dist/templates/usecase.test.js.map +1 -0
- package/dist/templates/view.d.ts +3 -0
- package/dist/templates/view.d.ts.map +1 -0
- package/dist/templates/view.js +112 -0
- package/dist/templates/view.js.map +1 -0
- package/dist/templates/view.test.d.ts +2 -0
- package/dist/templates/view.test.d.ts.map +1 -0
- package/dist/templates/view.test.js +71 -0
- package/dist/templates/view.test.js.map +1 -0
- package/dist/tools/addRoute.d.ts +3 -0
- package/dist/tools/addRoute.d.ts.map +1 -0
- package/dist/tools/addRoute.js +101 -0
- package/dist/tools/addRoute.js.map +1 -0
- package/dist/tools/createAnimation.d.ts +3 -0
- package/dist/tools/createAnimation.d.ts.map +1 -0
- package/dist/tools/createAnimation.js +53 -0
- package/dist/tools/createAnimation.js.map +1 -0
- package/dist/tools/createDomainService.d.ts +3 -0
- package/dist/tools/createDomainService.d.ts.map +1 -0
- package/dist/tools/createDomainService.js +82 -0
- package/dist/tools/createDomainService.js.map +1 -0
- package/dist/tools/createInterface.d.ts +3 -0
- package/dist/tools/createInterface.d.ts.map +1 -0
- package/dist/tools/createInterface.js +59 -0
- package/dist/tools/createInterface.js.map +1 -0
- package/dist/tools/createLoading.d.ts +3 -0
- package/dist/tools/createLoading.d.ts.map +1 -0
- package/dist/tools/createLoading.js +52 -0
- package/dist/tools/createLoading.js.map +1 -0
- package/dist/tools/createRepository.d.ts +3 -0
- package/dist/tools/createRepository.d.ts.map +1 -0
- package/dist/tools/createRepository.js +55 -0
- package/dist/tools/createRepository.js.map +1 -0
- package/dist/tools/createUiComponent.d.ts +3 -0
- package/dist/tools/createUiComponent.d.ts.map +1 -0
- package/dist/tools/createUiComponent.js +80 -0
- package/dist/tools/createUiComponent.js.map +1 -0
- package/dist/tools/createUseCase.d.ts +3 -0
- package/dist/tools/createUseCase.d.ts.map +1 -0
- package/dist/tools/createUseCase.js +52 -0
- package/dist/tools/createUseCase.js.map +1 -0
- package/dist/tools/createView.d.ts +3 -0
- package/dist/tools/createView.d.ts.map +1 -0
- package/dist/tools/createView.js +59 -0
- package/dist/tools/createView.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +25 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/tools.test.d.ts +2 -0
- package/dist/tools/tools.test.d.ts.map +1 -0
- package/dist/tools/tools.test.js +58 -0
- package/dist/tools/tools.test.js.map +1 -0
- package/dist/tools/validateArchitecture.d.ts +3 -0
- package/dist/tools/validateArchitecture.d.ts.map +1 -0
- package/dist/tools/validateArchitecture.js +134 -0
- package/dist/tools/validateArchitecture.js.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +18 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +34 -0
- package/dist/utils.test.js.map +1 -0
- 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
|
+
- [設定ファイル](#設定ファイル)
|