@xxmachina/components 19.21.8 → 19.24.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/extras/flow/index.d.ts +13 -3
- package/extras/flow/index.d.ts.map +1 -1
- package/features/query/index.d.ts.map +1 -1
- package/fesm2022/xxmachina-components-extras-flow.mjs +110 -11
- package/fesm2022/xxmachina-components-extras-flow.mjs.map +1 -1
- package/fesm2022/xxmachina-components-groups-query-form.mjs.map +1 -1
- package/fesm2022/xxmachina-components-molecules-inline-edit-field.mjs +117 -0
- package/fesm2022/xxmachina-components-molecules-inline-edit-field.mjs.map +1 -0
- package/fesm2022/xxmachina-components-molecules-weekly-header.mjs +2 -2
- package/fesm2022/xxmachina-components-molecules-weekly-header.mjs.map +1 -1
- package/fesm2022/xxmachina-components-organisms-calendar-section.mjs +2 -2
- package/fesm2022/xxmachina-components-organisms-calendar-section.mjs.map +1 -1
- package/fesm2022/xxmachina-components-organisms-terminal-input-section.mjs +19 -4
- package/fesm2022/xxmachina-components-organisms-terminal-input-section.mjs.map +1 -1
- package/fesm2022/xxmachina-components-organisms-xterm.mjs +849 -49
- package/fesm2022/xxmachina-components-organisms-xterm.mjs.map +1 -1
- package/fesm2022/xxmachina-components-pages-command-harness.mjs +28 -0
- package/fesm2022/xxmachina-components-pages-command-harness.mjs.map +1 -0
- package/fesm2022/xxmachina-components-pages-command.mjs +10 -6
- package/fesm2022/xxmachina-components-pages-command.mjs.map +1 -1
- package/fesm2022/xxmachina-components-pages-query.mjs +2 -2
- package/fesm2022/xxmachina-components-pages-query.mjs.map +1 -1
- package/fesm2022/xxmachina-components-pages-thread.mjs +2 -2
- package/fesm2022/xxmachina-components-pages-thread.mjs.map +1 -1
- package/fesm2022/xxmachina-components-services-message.mjs.map +1 -1
- package/fesm2022/xxmachina-components-templates-agent.mjs +151 -123
- package/fesm2022/xxmachina-components-templates-agent.mjs.map +1 -1
- package/fesm2022/xxmachina-components-templates-background.mjs +376 -242
- package/fesm2022/xxmachina-components-templates-background.mjs.map +1 -1
- package/fesm2022/xxmachina-components-templates-flow-nodes-group.mjs +164 -0
- package/fesm2022/xxmachina-components-templates-flow-nodes-group.mjs.map +1 -0
- package/fesm2022/xxmachina-components-templates-flow-nodes-issue.mjs +157 -0
- package/fesm2022/xxmachina-components-templates-flow-nodes-issue.mjs.map +1 -0
- package/fesm2022/xxmachina-components-templates-flow-nodes-task.mjs +154 -0
- package/fesm2022/xxmachina-components-templates-flow-nodes-task.mjs.map +1 -0
- package/fesm2022/xxmachina-components-templates-flow.mjs +337 -0
- package/fesm2022/xxmachina-components-templates-flow.mjs.map +1 -0
- package/fesm2022/xxmachina-components.mjs +2 -2
- package/fesm2022/xxmachina-components.mjs.map +1 -1
- package/groups/query-form/index.d.ts +3 -4
- package/groups/query-form/index.d.ts.map +1 -1
- package/index.d.ts.map +1 -1
- package/molecules/inline-edit-field/index.d.ts +32 -0
- package/molecules/inline-edit-field/index.d.ts.map +1 -0
- package/organisms/terminal-input-section/index.d.ts +2 -1
- package/organisms/terminal-input-section/index.d.ts.map +1 -1
- package/organisms/xterm/index.d.ts +176 -4
- package/organisms/xterm/index.d.ts.map +1 -1
- package/package.json +29 -13
- package/pages/command/harness/index.d.ts +14 -0
- package/pages/command/harness/index.d.ts.map +1 -0
- package/pages/command/index.d.ts +12 -4
- package/pages/command/index.d.ts.map +1 -1
- package/pages/query/index.d.ts +2 -2
- package/pages/query/index.d.ts.map +1 -1
- package/pages/query-v2/index.d.ts.map +1 -1
- package/services/command/index.d.ts.map +1 -1
- package/services/message/index.d.ts +3 -3
- package/services/message/index.d.ts.map +1 -1
- package/templates/agent/index.d.ts +11 -2
- package/templates/agent/index.d.ts.map +1 -1
- package/templates/background/index.d.ts +14 -20
- package/templates/background/index.d.ts.map +1 -1
- package/templates/flow/index.d.ts +61 -0
- package/templates/flow/index.d.ts.map +1 -0
- package/templates/flow/nodes/group/index.d.ts +44 -0
- package/templates/flow/nodes/group/index.d.ts.map +1 -0
- package/templates/flow/nodes/issue/index.d.ts +46 -0
- package/templates/flow/nodes/issue/index.d.ts.map +1 -0
- package/templates/flow/nodes/task/index.d.ts +37 -0
- package/templates/flow/nodes/task/index.d.ts.map +1 -0
- package/fesm2022/xxmachina-components-services-calendar.mjs +0 -25
- package/fesm2022/xxmachina-components-services-calendar.mjs.map +0 -1
- package/fesm2022/xxmachina-components-services-schedule.mjs +0 -51
- package/fesm2022/xxmachina-components-services-schedule.mjs.map +0 -1
- package/services/calendar/index.d.ts +0 -14
- package/services/calendar/index.d.ts.map +0 -1
- package/services/schedule/index.d.ts +0 -27
- package/services/schedule/index.d.ts.map +0 -1
|
@@ -1,16 +1,337 @@
|
|
|
1
1
|
import { provideComponent } from '@ng-atomic/core';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { input,
|
|
3
|
+
import { input, viewChild, afterNextRender, Component } from '@angular/core';
|
|
4
|
+
import * as THREE from 'three';
|
|
4
5
|
import { BackgroundTemplateStore } from '@ng-atomic/components/templates/background';
|
|
5
6
|
|
|
7
|
+
const particleVertexShader = /* glsl */ `
|
|
8
|
+
attribute vec3 velocity;
|
|
9
|
+
attribute float size;
|
|
10
|
+
|
|
11
|
+
uniform float uTime;
|
|
12
|
+
uniform vec2 uBounds;
|
|
13
|
+
|
|
14
|
+
varying vec3 vColor;
|
|
15
|
+
varying float vAlpha;
|
|
16
|
+
|
|
17
|
+
void main() {
|
|
18
|
+
vColor = color;
|
|
19
|
+
vAlpha = 1.0;
|
|
20
|
+
|
|
21
|
+
// GPU上で位置更新(時間ベース)
|
|
22
|
+
vec3 pos = position;
|
|
23
|
+
pos.x += velocity.x * uTime * 0.01;
|
|
24
|
+
pos.y += velocity.y * uTime * 0.01;
|
|
25
|
+
|
|
26
|
+
// 境界でラップアラウンド
|
|
27
|
+
pos.x = mod(pos.x + uBounds.x, uBounds.x * 2.0) - uBounds.x;
|
|
28
|
+
pos.y = mod(pos.y + uBounds.y, uBounds.y * 2.0) - uBounds.y;
|
|
29
|
+
|
|
30
|
+
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
|
|
31
|
+
gl_PointSize = size * (300.0 / -mvPosition.z);
|
|
32
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const particleFragmentShader = /* glsl */ `
|
|
37
|
+
varying vec3 vColor;
|
|
38
|
+
varying float vAlpha;
|
|
39
|
+
|
|
40
|
+
void main() {
|
|
41
|
+
// 中心からの距離
|
|
42
|
+
float dist = length(gl_PointCoord - vec2(0.5));
|
|
43
|
+
|
|
44
|
+
// 円形にクリップ
|
|
45
|
+
if (dist > 0.5) discard;
|
|
46
|
+
|
|
47
|
+
// 強いグロー効果(Canvas版のshadowBlur=15を再現)
|
|
48
|
+
float coreBrightness = exp(-dist * 8.0); // コア部分(非常に明るい)
|
|
49
|
+
float glowBrightness = exp(-dist * 2.5) * 0.6; // 外側のソフトグロー
|
|
50
|
+
float outerGlow = exp(-dist * 1.5) * 0.3; // さらに外側の淡いグロー
|
|
51
|
+
float glow = coreBrightness + glowBrightness + outerGlow;
|
|
52
|
+
|
|
53
|
+
// 色を強くブースト(黒背景で映える明るさに)
|
|
54
|
+
vec3 boostedColor = vColor * 1.5;
|
|
55
|
+
float alpha = min(glow * vAlpha, 1.0);
|
|
56
|
+
|
|
57
|
+
gl_FragColor = vec4(boostedColor, alpha);
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
class WebGLParticleSystem {
|
|
62
|
+
scene;
|
|
63
|
+
camera;
|
|
64
|
+
renderer;
|
|
65
|
+
particles;
|
|
66
|
+
lines;
|
|
67
|
+
clock;
|
|
68
|
+
config;
|
|
69
|
+
positions;
|
|
70
|
+
velocities;
|
|
71
|
+
isRunning = false;
|
|
72
|
+
frameCount = 0; // 接続線更新頻度制御用
|
|
73
|
+
constructor(config) {
|
|
74
|
+
this.config = {
|
|
75
|
+
container: config.container,
|
|
76
|
+
particleCount: config.particleCount ?? this.getOptimalParticleCount(),
|
|
77
|
+
connectionDistance: config.connectionDistance ?? 100, // パフォーマンス優先で短縮
|
|
78
|
+
baseHue: config.baseHue ?? -1, // -1 = 全色相ランダム
|
|
79
|
+
hueSpeed: config.hueSpeed ?? 30,
|
|
80
|
+
};
|
|
81
|
+
this.scene = new THREE.Scene();
|
|
82
|
+
this.scene.background = new THREE.Color(0x000000);
|
|
83
|
+
this.clock = new THREE.Clock();
|
|
84
|
+
this.positions = new Float32Array(this.config.particleCount * 3);
|
|
85
|
+
this.velocities = new Float32Array(this.config.particleCount * 3);
|
|
86
|
+
this.camera = this.createCamera();
|
|
87
|
+
this.renderer = this.createRenderer();
|
|
88
|
+
this.particles = this.createParticles();
|
|
89
|
+
this.lines = this.createLines();
|
|
90
|
+
this.scene.add(this.particles);
|
|
91
|
+
this.scene.add(this.lines);
|
|
92
|
+
this.setupResizeHandler();
|
|
93
|
+
this.setupVisibilityHandler();
|
|
94
|
+
}
|
|
95
|
+
getOptimalParticleCount() {
|
|
96
|
+
const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent);
|
|
97
|
+
// パフォーマンス優先:パーティクル数を削減
|
|
98
|
+
return isMobile ? 60 : 100;
|
|
99
|
+
}
|
|
100
|
+
createCamera() {
|
|
101
|
+
const { width, height } = this.getSize();
|
|
102
|
+
const camera = new THREE.PerspectiveCamera(75, width / height, 1, 2000);
|
|
103
|
+
camera.position.z = 400;
|
|
104
|
+
return camera;
|
|
105
|
+
}
|
|
106
|
+
createRenderer() {
|
|
107
|
+
const { width, height } = this.getSize();
|
|
108
|
+
const renderer = new THREE.WebGLRenderer({
|
|
109
|
+
antialias: true,
|
|
110
|
+
alpha: false, // 黒背景を強制(透明にしない)
|
|
111
|
+
});
|
|
112
|
+
renderer.setSize(width, height);
|
|
113
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
114
|
+
renderer.setClearColor(0x000000, 1); // 明示的に黒背景を設定
|
|
115
|
+
this.config.container.appendChild(renderer.domElement);
|
|
116
|
+
// Canvas styling - コンテナ内に配置(position: absoluteに変更)
|
|
117
|
+
renderer.domElement.style.position = 'absolute';
|
|
118
|
+
renderer.domElement.style.top = '0';
|
|
119
|
+
renderer.domElement.style.left = '0';
|
|
120
|
+
renderer.domElement.style.width = '100%';
|
|
121
|
+
renderer.domElement.style.height = '100%';
|
|
122
|
+
return renderer;
|
|
123
|
+
}
|
|
124
|
+
createParticles() {
|
|
125
|
+
const { particleCount, baseHue } = this.config;
|
|
126
|
+
const { width, height } = this.getSize();
|
|
127
|
+
const geometry = new THREE.BufferGeometry();
|
|
128
|
+
const colors = new Float32Array(particleCount * 3);
|
|
129
|
+
const sizes = new Float32Array(particleCount);
|
|
130
|
+
for (let i = 0; i < particleCount; i++) {
|
|
131
|
+
const i3 = i * 3;
|
|
132
|
+
// ランダム位置
|
|
133
|
+
this.positions[i3] = (Math.random() - 0.5) * width;
|
|
134
|
+
this.positions[i3 + 1] = (Math.random() - 0.5) * height;
|
|
135
|
+
this.positions[i3 + 2] = (Math.random() - 0.5) * 100;
|
|
136
|
+
// ランダム速度
|
|
137
|
+
this.velocities[i3] = (Math.random() - 0.5) * 50;
|
|
138
|
+
this.velocities[i3 + 1] = (Math.random() - 0.5) * 50;
|
|
139
|
+
this.velocities[i3 + 2] = 0;
|
|
140
|
+
// HSLカラー(baseHue < 0 なら全色相ランダム)
|
|
141
|
+
const hue = baseHue < 0
|
|
142
|
+
? Math.random() // 0-1 (全色相)
|
|
143
|
+
: (baseHue + Math.random() * 60) / 360;
|
|
144
|
+
// 彩度70%、明度60%で鮮やかに(Canvas版のshadowBlur効果を再現)
|
|
145
|
+
const color = new THREE.Color().setHSL(hue, 0.7, 0.6);
|
|
146
|
+
colors[i3] = color.r;
|
|
147
|
+
colors[i3 + 1] = color.g;
|
|
148
|
+
colors[i3 + 2] = color.b;
|
|
149
|
+
sizes[i] = Math.random() * 2 + 2; // サイズ2-4(パフォーマンス優先)
|
|
150
|
+
}
|
|
151
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(this.positions, 3));
|
|
152
|
+
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
|
153
|
+
geometry.setAttribute('velocity', new THREE.BufferAttribute(this.velocities, 3));
|
|
154
|
+
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
|
|
155
|
+
const material = new THREE.ShaderMaterial({
|
|
156
|
+
vertexShader: particleVertexShader,
|
|
157
|
+
fragmentShader: particleFragmentShader,
|
|
158
|
+
uniforms: {
|
|
159
|
+
uTime: { value: 0 },
|
|
160
|
+
uBounds: { value: new THREE.Vector2(width / 2, height / 2) },
|
|
161
|
+
},
|
|
162
|
+
transparent: true,
|
|
163
|
+
vertexColors: true,
|
|
164
|
+
blending: THREE.AdditiveBlending,
|
|
165
|
+
depthWrite: false,
|
|
166
|
+
});
|
|
167
|
+
return new THREE.Points(geometry, material);
|
|
168
|
+
}
|
|
169
|
+
createLines() {
|
|
170
|
+
const geometry = new THREE.BufferGeometry();
|
|
171
|
+
const material = new THREE.LineBasicMaterial({
|
|
172
|
+
vertexColors: true,
|
|
173
|
+
transparent: true,
|
|
174
|
+
blending: THREE.AdditiveBlending,
|
|
175
|
+
depthWrite: false,
|
|
176
|
+
});
|
|
177
|
+
return new THREE.LineSegments(geometry, material);
|
|
178
|
+
}
|
|
179
|
+
updateConnections() {
|
|
180
|
+
const { particleCount, connectionDistance, baseHue, hueSpeed } = this.config;
|
|
181
|
+
const positions = [];
|
|
182
|
+
const colors = [];
|
|
183
|
+
// 空間分割グリッド
|
|
184
|
+
const cellSize = connectionDistance;
|
|
185
|
+
const grid = new Map();
|
|
186
|
+
// パーティクルをグリッドに配置
|
|
187
|
+
for (let i = 0; i < particleCount; i++) {
|
|
188
|
+
const x = this.positions[i * 3];
|
|
189
|
+
const y = this.positions[i * 3 + 1];
|
|
190
|
+
const cellX = Math.floor(x / cellSize);
|
|
191
|
+
const cellY = Math.floor(y / cellSize);
|
|
192
|
+
const key = `${cellX},${cellY}`;
|
|
193
|
+
if (!grid.has(key))
|
|
194
|
+
grid.set(key, []);
|
|
195
|
+
grid.get(key).push(i);
|
|
196
|
+
}
|
|
197
|
+
// 接続線のhue(全色相でゆっくり変化)
|
|
198
|
+
const elapsed = this.clock.getElapsedTime();
|
|
199
|
+
const lineHue = baseHue < 0
|
|
200
|
+
? ((elapsed * hueSpeed) % 360) / 360
|
|
201
|
+
: (baseHue + (elapsed * hueSpeed) % 60) / 360;
|
|
202
|
+
// 色計算をキャッシュ(パフォーマンス向上)
|
|
203
|
+
const lineColor = new THREE.Color().setHSL(lineHue, 0.8, 0.65);
|
|
204
|
+
// 近傍セルのみ探索
|
|
205
|
+
for (const [key, indices] of grid.entries()) {
|
|
206
|
+
const [cx, cy] = key.split(',').map(Number);
|
|
207
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
208
|
+
for (let dy = -1; dy <= 1; dy++) {
|
|
209
|
+
const neighborKey = `${cx + dx},${cy + dy}`;
|
|
210
|
+
const neighborIndices = grid.get(neighborKey);
|
|
211
|
+
if (!neighborIndices)
|
|
212
|
+
continue;
|
|
213
|
+
for (const i of indices) {
|
|
214
|
+
for (const j of neighborIndices) {
|
|
215
|
+
if (i >= j)
|
|
216
|
+
continue;
|
|
217
|
+
const i3 = i * 3;
|
|
218
|
+
const j3 = j * 3;
|
|
219
|
+
const pdx = this.positions[i3] - this.positions[j3];
|
|
220
|
+
const pdy = this.positions[i3 + 1] - this.positions[j3 + 1];
|
|
221
|
+
const dist = Math.sqrt(pdx * pdx + pdy * pdy);
|
|
222
|
+
if (dist < connectionDistance) {
|
|
223
|
+
const alpha = (1 - dist / connectionDistance) * 0.7;
|
|
224
|
+
positions.push(this.positions[i3], this.positions[i3 + 1], this.positions[i3 + 2], this.positions[j3], this.positions[j3 + 1], this.positions[j3 + 2]);
|
|
225
|
+
// キャッシュした色を使用(パフォーマンス向上)
|
|
226
|
+
colors.push(lineColor.r * alpha, lineColor.g * alpha, lineColor.b * alpha, lineColor.r * alpha, lineColor.g * alpha, lineColor.b * alpha);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
this.lines.geometry.dispose();
|
|
234
|
+
this.lines.geometry = new THREE.BufferGeometry();
|
|
235
|
+
if (positions.length > 0) {
|
|
236
|
+
this.lines.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
237
|
+
this.lines.geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
updateParticlePositions(delta) {
|
|
241
|
+
const { width, height } = this.getSize();
|
|
242
|
+
const halfW = width / 2;
|
|
243
|
+
const halfH = height / 2;
|
|
244
|
+
for (let i = 0; i < this.config.particleCount; i++) {
|
|
245
|
+
const i3 = i * 3;
|
|
246
|
+
// 速度による移動
|
|
247
|
+
this.positions[i3] += this.velocities[i3] * delta;
|
|
248
|
+
this.positions[i3 + 1] += this.velocities[i3 + 1] * delta;
|
|
249
|
+
// 境界でラップアラウンド
|
|
250
|
+
if (this.positions[i3] > halfW)
|
|
251
|
+
this.positions[i3] = -halfW;
|
|
252
|
+
if (this.positions[i3] < -halfW)
|
|
253
|
+
this.positions[i3] = halfW;
|
|
254
|
+
if (this.positions[i3 + 1] > halfH)
|
|
255
|
+
this.positions[i3 + 1] = -halfH;
|
|
256
|
+
if (this.positions[i3 + 1] < -halfH)
|
|
257
|
+
this.positions[i3 + 1] = halfH;
|
|
258
|
+
}
|
|
259
|
+
this.particles.geometry.attributes['position'].needsUpdate = true;
|
|
260
|
+
}
|
|
261
|
+
animate = () => {
|
|
262
|
+
if (!this.isRunning)
|
|
263
|
+
return;
|
|
264
|
+
const delta = this.clock.getDelta();
|
|
265
|
+
const elapsed = this.clock.getElapsedTime();
|
|
266
|
+
// パーティクル位置更新
|
|
267
|
+
this.updateParticlePositions(delta);
|
|
268
|
+
// シェーダーuniform更新
|
|
269
|
+
const material = this.particles.material;
|
|
270
|
+
material.uniforms['uTime'].value = elapsed;
|
|
271
|
+
// 接続線更新(3フレームに1回にしてパフォーマンス向上)
|
|
272
|
+
this.frameCount++;
|
|
273
|
+
if (this.frameCount % 3 === 0) {
|
|
274
|
+
this.updateConnections();
|
|
275
|
+
}
|
|
276
|
+
// 描画
|
|
277
|
+
this.renderer.render(this.scene, this.camera);
|
|
278
|
+
requestAnimationFrame(this.animate);
|
|
279
|
+
};
|
|
280
|
+
getSize() {
|
|
281
|
+
return {
|
|
282
|
+
width: window.innerWidth,
|
|
283
|
+
height: window.innerHeight,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
setupResizeHandler() {
|
|
287
|
+
window.addEventListener('resize', () => {
|
|
288
|
+
const { width, height } = this.getSize();
|
|
289
|
+
this.camera.aspect = width / height;
|
|
290
|
+
this.camera.updateProjectionMatrix();
|
|
291
|
+
this.renderer.setSize(width, height);
|
|
292
|
+
const material = this.particles.material;
|
|
293
|
+
material.uniforms['uBounds'].value.set(width / 2, height / 2);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
setupVisibilityHandler() {
|
|
297
|
+
document.addEventListener('visibilitychange', () => {
|
|
298
|
+
if (document.hidden) {
|
|
299
|
+
this.stop();
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.start();
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
start() {
|
|
307
|
+
if (this.isRunning)
|
|
308
|
+
return;
|
|
309
|
+
this.isRunning = true;
|
|
310
|
+
this.clock.start();
|
|
311
|
+
requestAnimationFrame(this.animate);
|
|
312
|
+
}
|
|
313
|
+
stop() {
|
|
314
|
+
this.isRunning = false;
|
|
315
|
+
this.clock.stop();
|
|
316
|
+
}
|
|
317
|
+
dispose() {
|
|
318
|
+
this.stop();
|
|
319
|
+
this.particles.geometry.dispose();
|
|
320
|
+
this.particles.material.dispose();
|
|
321
|
+
this.lines.geometry.dispose();
|
|
322
|
+
this.lines.material.dispose();
|
|
323
|
+
this.renderer.dispose();
|
|
324
|
+
this.config.container.removeChild(this.renderer.domElement);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
6
328
|
class BackgroundTemplate {
|
|
7
329
|
title = input('');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
frame = 0;
|
|
330
|
+
container = viewChild.required('container');
|
|
331
|
+
particleSystem = null;
|
|
332
|
+
glitchInterval = null;
|
|
333
|
+
currentMessage = '(x_x) PROTOCOL.7 (x_x)';
|
|
334
|
+
isGlitching = false;
|
|
14
335
|
messages = [
|
|
15
336
|
'(x_x) PROTOCOL.7 (x_x)',
|
|
16
337
|
'[MACHINA:01] INITIALIZING...',
|
|
@@ -19,279 +340,92 @@ class BackgroundTemplate {
|
|
|
19
340
|
'【=◈︿◈=】LAYER:13【=◈︿◈=】',
|
|
20
341
|
'[▀▄▀▄▀▄] NAV¡GATOR [▄▀▄▀▄▀]',
|
|
21
342
|
'(╥﹏╥) ERROR_404 (╥﹏╥)',
|
|
22
|
-
`
|
|
23
|
-
╔═══════════════╗
|
|
24
|
-
║ PRESENT TIME. ║
|
|
25
|
-
╚═══════════════╝
|
|
26
|
-
`,
|
|
27
|
-
`
|
|
28
|
-
/\\_/\\ PROTOCOL
|
|
29
|
-
((@v@)) BREACH
|
|
30
|
-
()::() DETECTED
|
|
31
|
-
VV-VV
|
|
32
|
-
`,
|
|
33
343
|
'▌│█║▌║▌║ CONNECTING... ║▌║▌║█│▌'
|
|
34
344
|
];
|
|
35
|
-
|
|
345
|
+
messageIndex = 0;
|
|
36
346
|
constructor() {
|
|
37
347
|
afterNextRender(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
348
|
+
this.particleSystem = new WebGLParticleSystem({
|
|
349
|
+
container: this.container().nativeElement,
|
|
350
|
+
baseHue: 180, // シアン〜グリーン系(Lainテーマ)
|
|
351
|
+
connectionDistance: 80,
|
|
352
|
+
});
|
|
353
|
+
this.particleSystem.start();
|
|
354
|
+
// グリッチエフェクト(5秒ごと)
|
|
355
|
+
this.glitchInterval = window.setInterval(() => this.triggerGlitch(), 5000);
|
|
44
356
|
});
|
|
45
357
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
dx: (Math.random() - 0.5) * 1,
|
|
54
|
-
dy: (Math.random() - 0.5) * 1,
|
|
55
|
-
size: Math.random() * 1.5 + 0.5,
|
|
56
|
-
color: `hsl(${180 + Math.random() * 60}, ${70 + Math.random() * 30}%, ${40 + Math.random() * 60}%)`,
|
|
57
|
-
glitchOffset: Math.random() * 5
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
glitchEffect() {
|
|
61
|
-
const canvas = this.canvas()?.nativeElement;
|
|
62
|
-
if (!canvas)
|
|
63
|
-
return;
|
|
64
|
-
this.particles.forEach(p => {
|
|
65
|
-
if (Math.random() < 0.3) {
|
|
66
|
-
p.x = Math.random() * canvas.width;
|
|
67
|
-
p.y = Math.random() * canvas.height;
|
|
68
|
-
p.glitchOffset = Math.random() * 10;
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
this.currentMessage = (this.currentMessage + 1) % this.messages.length;
|
|
358
|
+
triggerGlitch() {
|
|
359
|
+
this.isGlitching = true;
|
|
360
|
+
this.messageIndex = (this.messageIndex + 1) % this.messages.length;
|
|
361
|
+
this.currentMessage = this.messages[this.messageIndex];
|
|
362
|
+
setTimeout(() => {
|
|
363
|
+
this.isGlitching = false;
|
|
364
|
+
}, 300);
|
|
72
365
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
ctx.textBaseline = 'top';
|
|
78
|
-
const glitchAmount = Math.random() * 5;
|
|
79
|
-
// メインテキスト
|
|
80
|
-
ctx.fillStyle = 'rgba(0, 255, 255, 0.8)';
|
|
81
|
-
const lines = message.split('\n');
|
|
82
|
-
lines.forEach((line, index) => {
|
|
83
|
-
ctx.fillText(line, 20 + glitchAmount, 20 + (index * 20));
|
|
84
|
-
});
|
|
85
|
-
// グリッチエフェクト
|
|
86
|
-
if (Math.random() < 0.3) {
|
|
87
|
-
ctx.fillStyle = 'rgba(255, 0, 255, 0.5)';
|
|
88
|
-
lines.forEach((line, index) => {
|
|
89
|
-
ctx.fillText(line, 20 - glitchAmount, 20 + (index * 20));
|
|
90
|
-
});
|
|
366
|
+
ngOnDestroy() {
|
|
367
|
+
this.particleSystem?.dispose();
|
|
368
|
+
if (this.glitchInterval !== null) {
|
|
369
|
+
clearInterval(this.glitchInterval);
|
|
91
370
|
}
|
|
92
|
-
// 座標表示
|
|
93
|
-
ctx.font = '12px "Courier New", monospace';
|
|
94
|
-
ctx.fillStyle = 'rgba(0, 255, 255, 0.4)';
|
|
95
|
-
ctx.fillText(`[X]: ${Math.floor(Math.random() * 1000)}`, canvas.width - 120, 20);
|
|
96
|
-
ctx.fillText(`[Y]: ${Math.floor(Math.random() * 1000)}`, canvas.width - 120, 40);
|
|
97
|
-
ctx.fillText(`(>_<) SYNC: ${Math.floor(Math.random() * 100)}%`, canvas.width - 160, 60);
|
|
98
371
|
}
|
|
99
|
-
animate = () => {
|
|
100
|
-
const canvas = this.canvas()?.nativeElement;
|
|
101
|
-
const ctx = this.ctx();
|
|
102
|
-
if (!canvas || !ctx)
|
|
103
|
-
return;
|
|
104
|
-
this.frame++;
|
|
105
|
-
ctx.fillStyle = 'rgba(0,0,0,0.1)';
|
|
106
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
107
|
-
if (this.frame % 30 === 0) {
|
|
108
|
-
ctx.strokeStyle = 'rgba(0, 255, 255, 0.1)';
|
|
109
|
-
ctx.lineWidth = 0.5;
|
|
110
|
-
for (let i = 0; i < canvas.width; i += 50) {
|
|
111
|
-
ctx.beginPath();
|
|
112
|
-
ctx.moveTo(i, 0);
|
|
113
|
-
ctx.lineTo(i, canvas.height);
|
|
114
|
-
ctx.stroke();
|
|
115
|
-
}
|
|
116
|
-
for (let i = 0; i < canvas.height; i += 50) {
|
|
117
|
-
ctx.beginPath();
|
|
118
|
-
ctx.moveTo(0, i);
|
|
119
|
-
ctx.lineTo(canvas.width, i);
|
|
120
|
-
ctx.stroke();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
this.particles.forEach(p => {
|
|
124
|
-
p.x += p.dx;
|
|
125
|
-
p.y += p.dy;
|
|
126
|
-
if (p.x < 0 || p.x > canvas.width) {
|
|
127
|
-
p.dx = -p.dx * 0.95;
|
|
128
|
-
p.dy += (Math.random() - 0.5) * 0.2;
|
|
129
|
-
}
|
|
130
|
-
if (p.y < 0 || p.y > canvas.height) {
|
|
131
|
-
p.dy = -p.dy * 0.95;
|
|
132
|
-
p.dx += (Math.random() - 0.5) * 0.2;
|
|
133
|
-
}
|
|
134
|
-
if (Math.random() < 0.98) {
|
|
135
|
-
ctx.shadowBlur = 10;
|
|
136
|
-
ctx.shadowColor = p.color;
|
|
137
|
-
ctx.fillStyle = p.color;
|
|
138
|
-
ctx.beginPath();
|
|
139
|
-
ctx.arc(p.x + (p.glitchOffset || 0), p.y, p.size, 0, Math.PI * 2);
|
|
140
|
-
ctx.fill();
|
|
141
|
-
ctx.shadowBlur = 0;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
for (let i = 0; i < this.particles.length; i++) {
|
|
145
|
-
for (let j = i + 1; j < this.particles.length; j++) {
|
|
146
|
-
const dx = this.particles[i].x - this.particles[j].x;
|
|
147
|
-
const dy = this.particles[i].y - this.particles[j].y;
|
|
148
|
-
const d = Math.sqrt(dx * dx + dy * dy);
|
|
149
|
-
if (d < 100) {
|
|
150
|
-
const alpha = (1 - d / 100) * 0.3;
|
|
151
|
-
ctx.beginPath();
|
|
152
|
-
ctx.strokeStyle = `hsla(${this.hue}, 100%, 70%, ${alpha})`;
|
|
153
|
-
ctx.lineWidth = 1;
|
|
154
|
-
ctx.moveTo(this.particles[i].x, this.particles[i].y);
|
|
155
|
-
ctx.lineTo(this.particles[j].x, this.particles[j].y);
|
|
156
|
-
ctx.stroke();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
this.drawText(ctx, canvas);
|
|
161
|
-
this.hue = 180 + Math.sin(this.frame * 0.01) * 30;
|
|
162
|
-
requestAnimationFrame(this.animate);
|
|
163
|
-
};
|
|
164
372
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: BackgroundTemplate, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
165
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: BackgroundTemplate, isStandalone: true, selector: "app-background-template", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
373
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: BackgroundTemplate, isStandalone: true, selector: "app-background-template", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
374
|
+
<div #container></div>
|
|
375
|
+
<div class="overlay">
|
|
376
|
+
<div class="scanlines"></div>
|
|
377
|
+
<div class="glitch-text" [class.glitch]="isGlitching">
|
|
378
|
+
{{ currentMessage }}
|
|
379
|
+
</div>
|
|
380
|
+
</div>
|
|
170
381
|
<div class="content">
|
|
171
382
|
@if (title()) {
|
|
172
383
|
<h1 class="title">{{ title() }}</h1>
|
|
173
384
|
}
|
|
174
385
|
<ng-content></ng-content>
|
|
175
386
|
</div>
|
|
176
|
-
`, isInline: true, styles: [":host{position:fixed;width:100%;height:100vh;color:#fff;z-index:-1}
|
|
387
|
+
`, isInline: true, styles: [":host{display:block;position:fixed;width:100%;height:100vh;color:#fff;z-index:-1}.overlay{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0}.scanlines{position:absolute;top:0;left:0;width:100%;height:100%;background:repeating-linear-gradient(0deg,rgba(0,0,0,.1) 0px,rgba(0,0,0,.1) 1px,transparent 1px,transparent 2px);opacity:.3}.glitch-text{position:absolute;top:20px;left:20px;font-family:Courier New,monospace;font-size:14px;color:#0ffc;text-shadow:0 0 10px rgba(0,255,255,.5);white-space:pre-line;transition:transform .1s}.glitch-text.glitch{animation:glitch .3s ease-in-out}@keyframes glitch{0%,to{transform:translate(0)}20%{transform:translate(-2px,2px)}40%{transform:translate(2px,-2px)}60%{transform:translate(-1px,-1px)}80%{transform:translate(1px,1px)}}.content{position:relative;z-index:1;padding:2rem}.title{font-size:2rem;margin-bottom:1rem;font-family:Courier New,monospace;text-shadow:0 0 10px rgba(0,255,255,.5)}\n"] });
|
|
177
388
|
}
|
|
178
389
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: BackgroundTemplate, decorators: [{
|
|
179
390
|
type: Component,
|
|
180
391
|
args: [{ selector: 'app-background-template', standalone: true, template: `
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
392
|
+
<div #container></div>
|
|
393
|
+
<div class="overlay">
|
|
394
|
+
<div class="scanlines"></div>
|
|
395
|
+
<div class="glitch-text" [class.glitch]="isGlitching">
|
|
396
|
+
{{ currentMessage }}
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
185
399
|
<div class="content">
|
|
186
400
|
@if (title()) {
|
|
187
401
|
<h1 class="title">{{ title() }}</h1>
|
|
188
402
|
}
|
|
189
403
|
<ng-content></ng-content>
|
|
190
404
|
</div>
|
|
191
|
-
`, styles: [":host{position:fixed;width:100%;height:100vh;color:#fff;z-index:-1}
|
|
405
|
+
`, styles: [":host{display:block;position:fixed;width:100%;height:100vh;color:#fff;z-index:-1}.overlay{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0}.scanlines{position:absolute;top:0;left:0;width:100%;height:100%;background:repeating-linear-gradient(0deg,rgba(0,0,0,.1) 0px,rgba(0,0,0,.1) 1px,transparent 1px,transparent 2px);opacity:.3}.glitch-text{position:absolute;top:20px;left:20px;font-family:Courier New,monospace;font-size:14px;color:#0ffc;text-shadow:0 0 10px rgba(0,255,255,.5);white-space:pre-line;transition:transform .1s}.glitch-text.glitch{animation:glitch .3s ease-in-out}@keyframes glitch{0%,to{transform:translate(0)}20%{transform:translate(-2px,2px)}40%{transform:translate(2px,-2px)}60%{transform:translate(-1px,-1px)}80%{transform:translate(1px,1px)}}.content{position:relative;z-index:1;padding:2rem}.title{font-size:2rem;margin-bottom:1rem;font-family:Courier New,monospace;text-shadow:0 0 10px rgba(0,255,255,.5)}\n"] }]
|
|
192
406
|
}], ctorParameters: () => [] });
|
|
193
407
|
|
|
194
408
|
class MachinaBackgroundTemplate {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
particles = [];
|
|
198
|
-
window = window;
|
|
199
|
-
hue = 0;
|
|
409
|
+
container = viewChild.required('container');
|
|
410
|
+
particleSystem = null;
|
|
200
411
|
constructor() {
|
|
201
412
|
afterNextRender(() => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
this.
|
|
413
|
+
this.particleSystem = new WebGLParticleSystem({
|
|
414
|
+
container: this.container().nativeElement,
|
|
415
|
+
// baseHue未指定 = 全色相ランダム(元の実装と同じ)
|
|
416
|
+
});
|
|
417
|
+
this.particleSystem.start();
|
|
207
418
|
});
|
|
208
419
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (!canvas)
|
|
212
|
-
return;
|
|
213
|
-
this.particles = Array.from({ length: 150 }, () => ({
|
|
214
|
-
x: Math.random() * canvas.width,
|
|
215
|
-
y: Math.random() * canvas.height,
|
|
216
|
-
dx: (Math.random() - 0.5) * 1.5,
|
|
217
|
-
dy: (Math.random() - 0.5) * 1.5,
|
|
218
|
-
size: Math.random() * 2 + 1,
|
|
219
|
-
color: `hsl(${Math.random() * 360}, 50%, 50%)`
|
|
220
|
-
}));
|
|
420
|
+
ngOnDestroy() {
|
|
421
|
+
this.particleSystem?.dispose();
|
|
221
422
|
}
|
|
222
|
-
animate = () => {
|
|
223
|
-
const canvas = this.canvas()?.nativeElement;
|
|
224
|
-
const ctx = this.ctx();
|
|
225
|
-
if (!canvas || !ctx)
|
|
226
|
-
return;
|
|
227
|
-
// Clear with fade effect
|
|
228
|
-
ctx.fillStyle = 'rgba(0,0,0,0.05)';
|
|
229
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
230
|
-
// Update and draw particles
|
|
231
|
-
this.particles.forEach(p => {
|
|
232
|
-
p.x += p.dx;
|
|
233
|
-
p.y += p.dy;
|
|
234
|
-
// Bounce off walls with slight randomization
|
|
235
|
-
if (p.x < 0 || p.x > canvas.width) {
|
|
236
|
-
p.dx = -p.dx * 0.99;
|
|
237
|
-
p.dy += (Math.random() - 0.5) * 0.2;
|
|
238
|
-
}
|
|
239
|
-
if (p.y < 0 || p.y > canvas.height) {
|
|
240
|
-
p.dy = -p.dy * 0.99;
|
|
241
|
-
p.dx += (Math.random() - 0.5) * 0.2;
|
|
242
|
-
}
|
|
243
|
-
// Draw particle with glow effect
|
|
244
|
-
ctx.shadowBlur = 15;
|
|
245
|
-
ctx.shadowColor = p.color;
|
|
246
|
-
ctx.fillStyle = p.color;
|
|
247
|
-
ctx.beginPath();
|
|
248
|
-
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
|
|
249
|
-
ctx.fill();
|
|
250
|
-
ctx.shadowBlur = 0;
|
|
251
|
-
});
|
|
252
|
-
// Draw connections with gradient effect
|
|
253
|
-
for (let i = 0; i < this.particles.length; i++) {
|
|
254
|
-
for (let j = i + 1; j < this.particles.length; j++) {
|
|
255
|
-
const dx = this.particles[i].x - this.particles[j].x;
|
|
256
|
-
const dy = this.particles[i].y - this.particles[j].y;
|
|
257
|
-
const d = Math.sqrt(dx * dx + dy * dy);
|
|
258
|
-
if (d < 120) {
|
|
259
|
-
const alpha = (1 - d / 120) * 0.5;
|
|
260
|
-
ctx.beginPath();
|
|
261
|
-
ctx.strokeStyle = `hsla(${this.hue}, 70%, 70%, ${alpha})`;
|
|
262
|
-
ctx.lineWidth = 2 * (1 - d / 120);
|
|
263
|
-
ctx.moveTo(this.particles[i].x, this.particles[i].y);
|
|
264
|
-
ctx.lineTo(this.particles[j].x, this.particles[j].y);
|
|
265
|
-
ctx.stroke();
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
// Slowly change hue for dynamic color effect
|
|
270
|
-
this.hue = (this.hue + 0.5) % 360;
|
|
271
|
-
requestAnimationFrame(this.animate);
|
|
272
|
-
};
|
|
273
423
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: MachinaBackgroundTemplate, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
274
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
275
|
-
<canvas #canvas
|
|
276
|
-
[width]="window.innerWidth"
|
|
277
|
-
[height]="window.innerHeight"
|
|
278
|
-
style="position: fixed; top: 0; left: 0; z-index: -1;">
|
|
279
|
-
</canvas>
|
|
280
|
-
`, isInline: true });
|
|
424
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.0.5", type: MachinaBackgroundTemplate, isStandalone: true, selector: "machina-templates-background", viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], ngImport: i0, template: `<div #container></div>`, isInline: true, styles: [":host{display:block;position:fixed;top:0;left:0;width:100%;height:100%;z-index:-1;pointer-events:none}\n"] });
|
|
281
425
|
}
|
|
282
426
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: MachinaBackgroundTemplate, decorators: [{
|
|
283
427
|
type: Component,
|
|
284
|
-
args: [{
|
|
285
|
-
selector: 'machina-templates-background',
|
|
286
|
-
standalone: true,
|
|
287
|
-
template: `
|
|
288
|
-
<canvas #canvas
|
|
289
|
-
[width]="window.innerWidth"
|
|
290
|
-
[height]="window.innerHeight"
|
|
291
|
-
style="position: fixed; top: 0; left: 0; z-index: -1;">
|
|
292
|
-
</canvas>
|
|
293
|
-
`
|
|
294
|
-
}]
|
|
428
|
+
args: [{ selector: 'machina-templates-background', standalone: true, template: `<div #container></div>`, styles: [":host{display:block;position:fixed;top:0;left:0;width:100%;height:100%;z-index:-1;pointer-events:none}\n"] }]
|
|
295
429
|
}], ctorParameters: () => [] });
|
|
296
430
|
|
|
297
431
|
function provideMachinaBackgroundTemplate() {
|