Stage 6 행성에 자기장 라인이 행성을 감싸며 바깥으로 번지는 연출
This commit is contained in:
@@ -472,6 +472,21 @@ class _Planet25DState extends State<Planet25D>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// Stage 6 — Figma `2024:20821` 「자기장(Field) 라인이 행성을 감싸며 외곽으로 방사됨」.
|
||||||
|
// 본체 뒤에 깔아 구면 바깥으로 뻗는 부분만 보이게 한다.
|
||||||
|
if (stage == 6)
|
||||||
|
Positioned.fill(
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: CustomPaint(
|
||||||
|
key: const ValueKey('planet-field-lines'),
|
||||||
|
painter: _FieldLinePainter(
|
||||||
|
t: t,
|
||||||
|
color: glow,
|
||||||
|
lowEffects: _lowEffects,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
// 6. 링 — 뒤쪽 절반. 본체 뒤에 깔린다.
|
// 6. 링 — 뒤쪽 절반. 본체 뒤에 깔린다.
|
||||||
if (ring)
|
if (ring)
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
@@ -902,6 +917,53 @@ class _OrbitPainter extends CustomPainter {
|
|||||||
old.lowEffects != lowEffects;
|
old.lowEffects != lowEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stage 6 자기장 — 양극을 잇는 고리를 좌우로 겹겹이 그리고, 밝은 띠가 안쪽에서 바깥 고리로
|
||||||
|
/// 번져 나간다(외곽 방사). 저사양은 고리 수만 줄인다.
|
||||||
|
class _FieldLinePainter extends CustomPainter {
|
||||||
|
const _FieldLinePainter({
|
||||||
|
required this.t,
|
||||||
|
required this.color,
|
||||||
|
required this.lowEffects,
|
||||||
|
});
|
||||||
|
final double t;
|
||||||
|
final Color color;
|
||||||
|
final bool lowEffects;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final c = size.center(Offset.zero);
|
||||||
|
final r = size.shortestSide * 0.42;
|
||||||
|
final loops = lowEffects ? 2 : 4;
|
||||||
|
// 방사 위치 0~1 — 한 주기에 네 번 안쪽에서 바깥으로.
|
||||||
|
final wave = (t * 4) % 1;
|
||||||
|
for (var i = 0; i < loops; i++) {
|
||||||
|
final k = (i + 1) / loops;
|
||||||
|
final w = r * (0.55 + 0.75 * k);
|
||||||
|
final h = r * (1.05 + 0.25 * k);
|
||||||
|
final glow = 1 - ((k - wave).abs() * 2.5).clamp(0.0, 1.0);
|
||||||
|
final paint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1.0 + glow * 1.2
|
||||||
|
..color = Color.lerp(color, Colors.white, 0.35)!
|
||||||
|
.withValues(alpha: (0.14 + 0.36 * glow) * (1 - k * 0.4));
|
||||||
|
for (final side in const [-1.0, 1.0]) {
|
||||||
|
canvas.drawOval(
|
||||||
|
Rect.fromCenter(
|
||||||
|
center: c + Offset(side * w / 2, 0),
|
||||||
|
width: w,
|
||||||
|
height: h * 2,
|
||||||
|
),
|
||||||
|
paint,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(_FieldLinePainter old) =>
|
||||||
|
old.t != t || old.color != color || old.lowEffects != lowEffects;
|
||||||
|
}
|
||||||
|
|
||||||
/// Stage 6: 폭죽 대신 구면 주위에 머무는 넓고 일정한 대기광.
|
/// Stage 6: 폭죽 대신 구면 주위에 머무는 넓고 일정한 대기광.
|
||||||
class _SustainedAura extends CustomPainter {
|
class _SustainedAura extends CustomPainter {
|
||||||
const _SustainedAura({required this.color, required this.lowEffects});
|
const _SustainedAura({required this.color, required this.lowEffects});
|
||||||
|
|||||||
@@ -182,4 +182,22 @@ void main() {
|
|||||||
await tester.pump(const Duration(seconds: 3));
|
await tester.pump(const Duration(seconds: 3));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Stage 6 은 자기장 라인이 행성을 감싼다(Figma 2024:20821) · Stage 5 는 없다', (tester) async {
|
||||||
|
Future<void> pumpStage(int stage) => tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Center(
|
||||||
|
child: Planet25D(
|
||||||
|
image: 'assets/figma/planet-home.png',
|
||||||
|
size: 200,
|
||||||
|
stage: stage,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await pumpStage(6);
|
||||||
|
expect(find.byKey(const ValueKey('planet-field-lines')), findsOneWidget);
|
||||||
|
await pumpStage(5);
|
||||||
|
expect(find.byKey(const ValueKey('planet-field-lines')), findsNothing);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user