HOME 을 Figma 「홈」 구성으로 — TODAY'S QUEST · 미니맵·확장 맵(프로토타입 v6.2) · 행성 정보 박스 · 인큐베이터 · 아티스트 소식 · HOT ARCHIVE · 인기 K-INSIDE
This commit is contained in:
@@ -30,7 +30,22 @@ class GalaxyMiniMap extends StatefulWidget {
|
||||
required this.data,
|
||||
required this.onOpen,
|
||||
this.size = 140,
|
||||
});
|
||||
}) : expanded = false,
|
||||
onOpenPlanet = null;
|
||||
|
||||
/// 「GALAXY 맵 확장」 — Figma 「홈_초기사용자」(`343:211127`)의 히어로 전체 갤럭시 맵.
|
||||
/// 부모 크기를 채우고 모든 행성에 프로토타입 HUD 를 그린다. 설명 프레임 「갤럭시맵 화면」
|
||||
/// (`2008:14486`)의 동작 — 끌어 회전(프로토타입 View Rotation ±180° · 관성 없음) ·
|
||||
/// 두 손가락 줌인/줌아웃 · 행성 탭 = 화면 중심 전환 · HUD 탭 = [onOpenPlanet](FPI 상세).
|
||||
const GalaxyMiniMap.expanded({
|
||||
super.key,
|
||||
required this.data,
|
||||
required ValueChanged<PlanetNode> this.onOpenPlanet,
|
||||
}) : expanded = true,
|
||||
onOpen = _noop,
|
||||
size = 0;
|
||||
|
||||
static void _noop() {}
|
||||
|
||||
final GalaxySnapshot data;
|
||||
final VoidCallback onOpen;
|
||||
@@ -38,13 +53,18 @@ class GalaxyMiniMap extends StatefulWidget {
|
||||
/// 정사각 한 변. HOME 은 약 140pt(C-105 · 자리는 C-113 → `HomeHero.miniMapAlignment`).
|
||||
final double size;
|
||||
|
||||
final bool expanded;
|
||||
final ValueChanged<PlanetNode>? onOpenPlanet;
|
||||
|
||||
@override
|
||||
State<GalaxyMiniMap> createState() => _GalaxyMiniMapState();
|
||||
}
|
||||
|
||||
class _GalaxyMiniMapState extends State<GalaxyMiniMap>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final _painter = GalaxyMiniMapPainter();
|
||||
late final _painter = widget.expanded
|
||||
? GalaxyMiniMapPainter.figmaScale()
|
||||
: GalaxyMiniMapPainter();
|
||||
late final Ticker _ticker = createTicker(_tick);
|
||||
Duration _last = Duration.zero;
|
||||
|
||||
@@ -92,8 +112,58 @@ class _GalaxyMiniMapState extends State<GalaxyMiniMap>
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
double _zoomStart = 1;
|
||||
|
||||
Widget _expanded(BuildContext context) {
|
||||
final mine = widget.data.mine;
|
||||
return LayoutBuilder(
|
||||
builder: (context, box) => Semantics(
|
||||
label: [
|
||||
if (mine != null)
|
||||
...GalaxyMiniMapPainter.hudLines(mine)
|
||||
else
|
||||
'GALAXY',
|
||||
].join(' · '),
|
||||
onTap: mine == null ? null : () => widget.onOpenPlanet!(mine),
|
||||
child: GestureDetector(
|
||||
excludeFromSemantics: true,
|
||||
onScaleStart: (_) => _zoomStart = _painter.zoom,
|
||||
onScaleUpdate: (d) {
|
||||
if (d.pointerCount > 1) {
|
||||
_painter.zoomTo(_zoomStart * d.scale);
|
||||
} else {
|
||||
_painter.turn(d.focalPointDelta.dx / box.maxWidth * math.pi);
|
||||
}
|
||||
if (!_ticker.isActive) _painter.settle();
|
||||
},
|
||||
onTapUp: (d) {
|
||||
final hit = _painter.hitAt(d.localPosition);
|
||||
if (hit == null) return;
|
||||
if (hit.hud) {
|
||||
widget.onOpenPlanet!(hit.planet);
|
||||
} else {
|
||||
_painter.focus(hit.planet.id);
|
||||
if (!_ticker.isActive) _painter.settle();
|
||||
}
|
||||
},
|
||||
child: ExcludeSemantics(
|
||||
child: RepaintBoundary(
|
||||
child: CustomPaint(
|
||||
size: box.biggest,
|
||||
painter: _painter,
|
||||
isComplex: true,
|
||||
willChange: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.expanded) return _expanded(context);
|
||||
final mine = widget.data.mine;
|
||||
return Semantics(
|
||||
button: true,
|
||||
@@ -153,7 +223,7 @@ const _emerald = Color(0xFF10B981);
|
||||
|
||||
/// 행성 색 — 팬덤 `colorKey` 를 행성 색 팔레트([planetColors])로 칠한다.
|
||||
/// 키가 없거나 모르는 값이면 FPI 순번으로 프로토타입 팔레트를 돈다.
|
||||
Color _planetColor(PlanetNode p, int fpiIndex) =>
|
||||
Color galaxyPlanetColor(PlanetNode p, int fpiIndex) =>
|
||||
planetColorOf(p.colorKey) ?? _palette[fpiIndex % _palette.length];
|
||||
|
||||
/// 프로토타입 게이지 기본값. 조절 UI 는 없다(C-51).
|
||||
@@ -201,6 +271,10 @@ class _Body {
|
||||
double wz = 0;
|
||||
double depth = 0;
|
||||
double hudW = 0;
|
||||
|
||||
/// 마지막 프레임의 화면 좌표·반지름·HUD 상자(탭 판정용).
|
||||
double sx = 0, sy = 0, sr = 0;
|
||||
Rect hudRect = Rect.zero;
|
||||
ui.Picture? hud;
|
||||
ui.Picture? sphere;
|
||||
Float32List sat = Float32List(0);
|
||||
@@ -273,6 +347,8 @@ ui.Picture _hudPicture(PlanetNode p, Color color, double share) {
|
||||
text: text,
|
||||
style: TextStyle(
|
||||
fontFamily: 'monospace',
|
||||
// 프로토타입 JetBrains Mono 대신 기기 고정폭(Android monospace · iOS Menlo).
|
||||
fontFamilyFallback: const ['Menlo', 'Courier', AppFonts.body],
|
||||
fontSize: size,
|
||||
fontWeight: weight,
|
||||
color: c,
|
||||
@@ -343,8 +419,27 @@ ui.Picture _spherePicture(Color c) {
|
||||
|
||||
/// 미니맵 장면 상태와 그리기. 상태는 위젯이 [advance]·[settle] 로 움직인다.
|
||||
class GalaxyMiniMapPainter extends CustomPainter {
|
||||
GalaxyMiniMapPainter() : this._(ValueNotifier<int>(0));
|
||||
GalaxyMiniMapPainter._(this._frame) : super(repaint: _frame);
|
||||
GalaxyMiniMapPainter() : this._(ValueNotifier<int>(0), null);
|
||||
|
||||
/// HOME 「GALAXY 맵 확장」 — Figma `343:211127` 축척. 화면 크기와 무관하게 초점 거리를
|
||||
/// [figmaFocal] 로 고정하고, HUD 카드는 [figmaHud] 고정 크기로 그린다.
|
||||
GalaxyMiniMapPainter.figmaScale() : this._(ValueNotifier<int>(0), figmaFocal);
|
||||
|
||||
GalaxyMiniMapPainter._(this._frame, this.fixedFocal) : super(repaint: _frame);
|
||||
|
||||
/// 고정 초점 거리(pt). null 이면 프로토타입처럼 세로 시야각 70°(`focal = h/2/tan35°`).
|
||||
final double? fixedFocal;
|
||||
|
||||
/// Figma `343:211127` 은 히어로(375)에 프로토타입 캡처(801×555)를 원래 픽셀 크기로 넣었다
|
||||
/// (y124 · 가로 가운데 x−213). 그 캡처의 내 행성(NewJeans, FPI 3200 → 반지름 31 × Mass 1.5)
|
||||
/// 지름이 38pt 다(Figma F1-05 · 343:211127 실측).
|
||||
/// `지름 = 2 × 46.5 × focal / 4031(카메라 거리)` → focal ≈ 1650pt. 같은 시야각이면
|
||||
/// 창 높이 약 2,310px 의 장면이다 — 556pt 창의 프로토타입보다 약 4.2배 크다.
|
||||
static const figmaFocal = 1650.0;
|
||||
|
||||
/// Figma 캡처의 내 행성 HUD 카드 실측 약 144×68pt → 텍스처 비율 2:1 로 144×72.
|
||||
/// 글자는 텍스처(512) 기준 이름 50 → 14pt · FPI 40 → 11pt · RANK/LIVE 24 → 6.75pt.
|
||||
static const figmaHud = Size(144, 72);
|
||||
|
||||
final ValueNotifier<int> _frame;
|
||||
|
||||
@@ -367,6 +462,43 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
double _gx = 0;
|
||||
double _gz = 0;
|
||||
|
||||
/// 확장 맵의 줌(초점 거리 배율). 별밭은 그대로 두고 장면만 키운다.
|
||||
double zoom = 1;
|
||||
static const minZoom = 0.5, maxZoom = 3.0;
|
||||
void zoomTo(double z) {
|
||||
zoom = z.clamp(minZoom, maxZoom);
|
||||
_frame.value++;
|
||||
}
|
||||
|
||||
/// 확장 맵에서 고른 행성 — 카메라가 이 행성을 가운데로 따라간다(없으면 내 행성).
|
||||
_Body? _focus;
|
||||
void focus(String id) => _focus = _bodies[id] ?? _focus;
|
||||
|
||||
@visibleForTesting
|
||||
String? get focusId => (_focus ?? _mine)?.id;
|
||||
|
||||
/// 마지막 프레임 기준 탭 판정 — HUD 카드가 위(프로토타입 depthTest: false)라 먼저 본다.
|
||||
({PlanetNode planet, bool hud})? hitAt(Offset p) {
|
||||
for (final b in _order.reversed) {
|
||||
if (b.hudRect.contains(p)) return (planet: b.node, hud: true);
|
||||
}
|
||||
for (final b in _order.reversed) {
|
||||
// 작은 행성도 손끝으로 잡히게 최소 반경 24.
|
||||
if ((Offset(b.sx, b.sy) - p).distance <= math.max(b.sr, 24)) {
|
||||
return (planet: b.node, hud: false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 행성의 마지막 화면 좌표 — 테스트가 탭할 자리.
|
||||
@visibleForTesting
|
||||
Offset? screenOf(String id) =>
|
||||
_bodies[id] == null ? null : Offset(_bodies[id]!.sx, _bodies[id]!.sy);
|
||||
|
||||
@visibleForTesting
|
||||
Rect? hudRectOf(String id) => _bodies[id]?.hudRect;
|
||||
|
||||
/// 그리는 행성 수(내 행성은 순위 밖이어도 더한다).
|
||||
static const maxPlanets = 10;
|
||||
|
||||
@@ -512,7 +644,7 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
(_bodies[p.id] ??= _Body(
|
||||
p.id,
|
||||
_bodies.length + 1.0,
|
||||
)).set(p, _planetColor(p, i), share);
|
||||
)).set(p, galaxyPlanetColor(p, i), share);
|
||||
}
|
||||
final ids = {for (final p in shown) p.id};
|
||||
_bodies.removeWhere((id, b) {
|
||||
@@ -524,6 +656,7 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
..clear()
|
||||
..addAll(_bodies.values);
|
||||
_mine = _order.where((b) => b.node.isMine).firstOrNull;
|
||||
if (_focus != null && !_bodies.containsValue(_focus)) _focus = null;
|
||||
_place(0);
|
||||
_frame.value++;
|
||||
}
|
||||
@@ -559,7 +692,7 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
void _place(double follow) {
|
||||
final c = math.cos(_rot);
|
||||
final s = math.sin(_rot);
|
||||
if (_mine case final m?) {
|
||||
if (_focus ?? _mine case final m?) {
|
||||
final a = _angle(m);
|
||||
final lx = math.cos(a) * m.rad;
|
||||
final lz = math.sin(a) * m.rad;
|
||||
@@ -679,9 +812,10 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final focal = size.height / 2 / _tanHalfFov;
|
||||
if (size != _bgSize) _buildBackground(size, focal);
|
||||
final bgFocal = size.height / 2 / _tanHalfFov;
|
||||
if (size != _bgSize) _buildBackground(size, bgFocal);
|
||||
canvas.drawPicture(_bg!);
|
||||
final focal = (fixedFocal ?? bgFocal) * zoom;
|
||||
|
||||
// 궤도 링 — 갤럭시 원점 중심, 두께 = 반지름/100, 흰색 15%.
|
||||
_project(_gx, 0, _gz, focal, size);
|
||||
@@ -747,6 +881,10 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
|
||||
// 광륜 + 구체.
|
||||
final rPx = r * focal / d;
|
||||
b
|
||||
..sx = px
|
||||
..sy = py
|
||||
..sr = rPx;
|
||||
canvas.save();
|
||||
canvas.translate(px, py);
|
||||
canvas.scale(rPx);
|
||||
@@ -778,17 +916,41 @@ class GalaxyMiniMapPainter extends CustomPainter {
|
||||
final hudHeight = 57.5 * f;
|
||||
// [fullHudMin] 보다 작으면 프로토타입 카드는 몇 px 라 읽히지 않는다 — 내 행성만
|
||||
// 간략 카드로 그리고 다른 행성 카드는 뺀다(궤도·행성만).
|
||||
final full = size.width >= fullHudMin;
|
||||
final full = fixedFocal != null || size.width >= fullHudMin;
|
||||
for (final b in _order) {
|
||||
b.hudW = 0;
|
||||
b.hudRect = Rect.zero;
|
||||
if (!full && !identical(b, _mine)) continue;
|
||||
if (b.depth < b.baseR * _scale * 2) continue;
|
||||
final y = _scale * (b.baseR * _scale + hudHeight / 2 + 2);
|
||||
_project(b.wx, y, b.wz, focal, size);
|
||||
if (_sd < 1) continue;
|
||||
final w = 115 * f * _scale * focal / _sd;
|
||||
if (fixedFocal != null) {
|
||||
// 고정 크기 카드 — 장면 축척 · 줌과 무관하게 같은 크기. 아래 변을 프로토타입 HUD
|
||||
// 아래 변 자리(행성 위 HUD Dist 2)에 둔다.
|
||||
const hud = figmaHud;
|
||||
_project(b.wx, _scale * (b.baseR * _scale + 2), b.wz, focal, size);
|
||||
if (_sd < 1) continue;
|
||||
final rect = Rect.fromLTWH(
|
||||
_sx - hud.width / 2,
|
||||
_sy - hud.height,
|
||||
hud.width,
|
||||
hud.height,
|
||||
);
|
||||
b
|
||||
..hudW = hud.width
|
||||
..hudRect = rect;
|
||||
canvas.save();
|
||||
canvas.translate(rect.left, rect.top);
|
||||
canvas.scale(hud.width / _hudW, hud.height / _hudH);
|
||||
canvas.drawPicture(b.hud!);
|
||||
canvas.restore();
|
||||
continue;
|
||||
}
|
||||
if (full) {
|
||||
b.hudW = w;
|
||||
b.hudRect = Rect.fromLTWH(_sx - w / 2, _sy - w / 4, w, w / 2);
|
||||
canvas.save();
|
||||
canvas.translate(_sx - w / 2, _sy - w / 4);
|
||||
canvas.scale(w / _hudW, w / 2 / _hudH);
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import '../galaxy_data.dart';
|
||||
import 'galaxy_mini_map.dart';
|
||||
|
||||
/// HOME GALAXY 미니맵 · 「GALAXY 맵 확장」 — 발주사 프로토타입 v6.2 HTML 을 그대로 띄운다
|
||||
/// (`assets/galaxy/uzu_hud.html` · 9/22 D-6 · 2026-10-05 대표 지시 「html 을 클론코딩하듯」).
|
||||
///
|
||||
/// 한 위젯이 두 모드를 다 맡는다. [expanded] 가 바뀌면 WebView 를 새로 만들지 않고 JS
|
||||
/// `setMode` 만 부른다 — HOME 은 같은 [GlobalKey] 로 미니맵 자리와 확장 자리 사이를 옮긴다.
|
||||
///
|
||||
/// - 데이터: [GalaxySnapshot] 의 FPI 상위 10 + 내 행성 → `setGalaxy(json)`.
|
||||
/// - 이벤트: HTML 이 `FanuzuBridge.postMessage` 로 보낸다 — `open`(미니맵 탭) · `hud`(HUD 탭 →
|
||||
/// [onOpenPlanet]) · `planet`(행성 탭, 중심 전환은 HTML 이 이미 했다).
|
||||
/// - 화면 밖 · 다른 화면에 가림 · 앱 백그라운드면 `fanuzuPause(true)` 로 rAF 를 멈춘다.
|
||||
/// - 플랫폼 뷰가 없는 곳(위젯 테스트 · 데스크톱)에서는 같은 장면을 옮긴 [GalaxyMiniMap] 으로 대신한다.
|
||||
class GalaxyWebView extends StatefulWidget {
|
||||
const GalaxyWebView({
|
||||
super.key,
|
||||
required this.data,
|
||||
required this.expanded,
|
||||
required this.onOpen,
|
||||
required this.onOpenPlanet,
|
||||
this.miniSize = 93,
|
||||
});
|
||||
|
||||
final GalaxySnapshot data;
|
||||
final bool expanded;
|
||||
final double miniSize;
|
||||
final VoidCallback onOpen;
|
||||
final ValueChanged<PlanetNode> onOpenPlanet;
|
||||
|
||||
/// WebView 를 쓸 수 있는가. 테스트에서 끄거나 켤 수 있다.
|
||||
static bool enabled =
|
||||
!kIsWeb &&
|
||||
(Platform.isAndroid || Platform.isIOS) &&
|
||||
!Platform.environment.containsKey('FLUTTER_TEST');
|
||||
|
||||
/// HTML 로 넘기는 행성 목록 — FPI 상위 10 + 순위 밖 내 행성(미니맵 painter 와 같은 규칙).
|
||||
@visibleForTesting
|
||||
static List<Map<String, Object>> payload(GalaxySnapshot data) {
|
||||
final byFpi = [...data.planets]..sort((a, b) => b.fpi.compareTo(a.fpi));
|
||||
final shown = byFpi.take(GalaxyMiniMapPainter.maxPlanets).toList();
|
||||
final mine = data.mine;
|
||||
if (mine != null && !shown.contains(mine)) shown.add(mine);
|
||||
return [
|
||||
for (final (i, p) in shown.indexed)
|
||||
{
|
||||
'id': p.id,
|
||||
'name': p.name,
|
||||
'rank': p.rank,
|
||||
'fpi': p.fpi,
|
||||
'live': p.online,
|
||||
'color': galaxyPlanetColor(p, i).toARGB32() & 0xFFFFFF,
|
||||
'mine': p.isMine,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
State<GalaxyWebView> createState() => _GalaxyWebViewState();
|
||||
}
|
||||
|
||||
class _GalaxyWebViewState extends State<GalaxyWebView>
|
||||
with WidgetsBindingObserver {
|
||||
WebViewController? _web;
|
||||
bool _ready = false;
|
||||
bool? _paused;
|
||||
bool _foreground = true;
|
||||
ScrollPosition? _scroll;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (!GalaxyWebView.enabled) return;
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_web = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setBackgroundColor(Colors.transparent)
|
||||
..addJavaScriptChannel('FanuzuBridge', onMessageReceived: _onMessage)
|
||||
..loadFlutterAsset('assets/galaxy/uzu_hud.html');
|
||||
}
|
||||
|
||||
void _js(String code) {
|
||||
if (_ready) _web?.runJavaScript(code);
|
||||
}
|
||||
|
||||
void _push() {
|
||||
_js('setMode(${jsonEncode(widget.expanded ? 'expanded' : 'mini')})');
|
||||
_js('setGalaxy(${jsonEncode(GalaxyWebView.payload(widget.data))})');
|
||||
}
|
||||
|
||||
void _onMessage(JavaScriptMessage m) {
|
||||
final msg = jsonDecode(m.message) as Map<String, dynamic>;
|
||||
switch (msg['type']) {
|
||||
case 'ready':
|
||||
_ready = true;
|
||||
_push();
|
||||
_paused = null;
|
||||
_syncPause();
|
||||
case 'open':
|
||||
widget.onOpen();
|
||||
case 'hud':
|
||||
final p = widget.data.planets
|
||||
.where((p) => p.id == msg['id'])
|
||||
.firstOrNull;
|
||||
if (p != null) widget.onOpenPlanet(p);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(GalaxyWebView old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (_web == null) return;
|
||||
if (!identical(old.data, widget.data)) {
|
||||
_push();
|
||||
} else if (old.expanded != widget.expanded) {
|
||||
_js('setMode(${jsonEncode(widget.expanded ? 'expanded' : 'mini')})');
|
||||
}
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _syncPause());
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (_web == null) return;
|
||||
final scroll = Scrollable.maybeOf(context)?.position;
|
||||
if (!identical(scroll, _scroll)) {
|
||||
_scroll?.removeListener(_syncPause);
|
||||
_scroll = scroll?..addListener(_syncPause);
|
||||
}
|
||||
// 다른 화면이 위에 올라오거나(ModalRoute) 탭이 바뀌면(TickerMode) 다시 판단한다.
|
||||
ModalRoute.of(context);
|
||||
TickerMode.valuesOf(context).enabled;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _syncPause());
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
_foreground = state == AppLifecycleState.resumed;
|
||||
_syncPause();
|
||||
}
|
||||
|
||||
bool get _visible {
|
||||
if (!mounted || !_foreground || !TickerMode.valuesOf(context).enabled) return false;
|
||||
if (ModalRoute.of(context)?.isCurrent == false) return false;
|
||||
final box = context.findRenderObject();
|
||||
if (box is! RenderBox || !box.attached || !box.hasSize) return true;
|
||||
final top = box.localToGlobal(Offset.zero).dy;
|
||||
return top + box.size.height > 0 && top < MediaQuery.sizeOf(context).height;
|
||||
}
|
||||
|
||||
void _syncPause() {
|
||||
if (!_ready || !mounted) return;
|
||||
final pause = !_visible;
|
||||
if (pause == _paused) return;
|
||||
_paused = pause;
|
||||
_js('fanuzuPause($pause)');
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scroll?.removeListener(_syncPause);
|
||||
if (_web != null) WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final web = _web;
|
||||
if (web == null) {
|
||||
return widget.expanded
|
||||
? GalaxyMiniMap.expanded(
|
||||
data: widget.data,
|
||||
onOpenPlanet: widget.onOpenPlanet,
|
||||
)
|
||||
: GalaxyMiniMap(
|
||||
size: widget.miniSize,
|
||||
data: widget.data,
|
||||
onOpen: widget.onOpen,
|
||||
);
|
||||
}
|
||||
final view = WebViewWidget(
|
||||
controller: web,
|
||||
// 확장 맵은 끌기 · 핀치를 모두 장면이 받는다(설명 프레임 2008:14486). 미니맵은 가로 끌기
|
||||
// (회전)와 탭만 — 세로 끌기는 HOME 목록 스크롤로 남긴다.
|
||||
gestureRecognizers: widget.expanded
|
||||
? {Factory<OneSequenceGestureRecognizer>(EagerGestureRecognizer.new)}
|
||||
: {
|
||||
Factory<OneSequenceGestureRecognizer>(
|
||||
HorizontalDragGestureRecognizer.new,
|
||||
),
|
||||
Factory<OneSequenceGestureRecognizer>(TapGestureRecognizer.new),
|
||||
},
|
||||
);
|
||||
return widget.expanded
|
||||
? view
|
||||
: SizedBox.square(dimension: widget.miniSize, child: view);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user