Finish first pass of home illustrations
This commit is contained in:
parent
859f76d8ce
commit
be4e3c1ea4
@ -21,7 +21,7 @@ class AppScrollBehavior extends ScrollBehavior {
|
|||||||
// TODO: Finalize scrollbar strategy (Do we use them at all? Where specifically?)
|
// TODO: Finalize scrollbar strategy (Do we use them at all? Where specifically?)
|
||||||
@override
|
@override
|
||||||
Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) {
|
Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) {
|
||||||
return child;
|
//return child;
|
||||||
return PlatformInfo.isAndroid
|
return PlatformInfo.isAndroid
|
||||||
? RawScrollbar(controller: details.controller, child: child)
|
? RawScrollbar(controller: details.controller, child: child)
|
||||||
: CupertinoScrollbar(controller: details.controller, child: child);
|
: CupertinoScrollbar(controller: details.controller, child: child);
|
||||||
|
@ -180,37 +180,3 @@ class _ButtonPressEffectState extends State<_ButtonPressEffect> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is currently unused, and can probably be removed:
|
|
||||||
// This is a very simple button for elements that don't require button UI (states, focus, etc)
|
|
||||||
// For example panel backgrounds.
|
|
||||||
class BasicBtn extends StatelessWidget {
|
|
||||||
const BasicBtn({
|
|
||||||
required this.onPressed,
|
|
||||||
required this.semanticLabel,
|
|
||||||
this.behavior = HitTestBehavior.opaque,
|
|
||||||
this.enableFeedback = true,
|
|
||||||
this.child,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final VoidCallback onPressed;
|
|
||||||
final String? semanticLabel;
|
|
||||||
final HitTestBehavior behavior;
|
|
||||||
final bool enableFeedback;
|
|
||||||
final Widget? child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Widget button = GestureDetector(
|
|
||||||
excludeFromSemantics: true,
|
|
||||||
onTap: enableFeedback ? Feedback.wrapForTap(onPressed, context) : onPressed,
|
|
||||||
behavior: behavior,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (semanticLabel != null) button = Semantics(label: semanticLabel, button: true, container: true, child: button);
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -12,7 +12,13 @@ class ChichenItzaIllustration extends StatelessWidget {
|
|||||||
final fgColor = WonderType.chichenItza.fgColor;
|
final fgColor = WonderType.chichenItza.fgColor;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WonderIllustrationBuilder(config: config, bgBuilder: _buildBg, mgBuilder: _buildMg, fgBuilder: _buildFg);
|
return WonderIllustrationBuilder(
|
||||||
|
config: config,
|
||||||
|
bgBuilder: _buildBg,
|
||||||
|
mgBuilder: _buildMg,
|
||||||
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.chichenItza,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildBg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildBg(BuildContext context, Animation<double> anim) {
|
||||||
@ -26,21 +32,13 @@ class ChichenItzaIllustration extends StatelessWidget {
|
|||||||
flipY: true,
|
flipY: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: Alignment(config.shortMode ? .25 : .5, config.shortMode ? 1 : -.15),
|
fileName: 'sun.png',
|
||||||
child: WonderHero(
|
initialOffset: Offset(0, 20),
|
||||||
config,
|
enableHero: true,
|
||||||
'chichen-sun',
|
heightFactor: .25,
|
||||||
child: FractionalTranslation(
|
minHeight: 200,
|
||||||
translation: Offset(0, -.2 * anim.value),
|
fractionalOffset: Offset(1, config.shortMode ? 0 : -.5),
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/sun.png',
|
|
||||||
width: config.shortMode ? 100 : 200,
|
|
||||||
cacheWidth: context.widthPx.round() * 2,
|
|
||||||
opacity: anim,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -48,90 +46,126 @@ class ChichenItzaIllustration extends StatelessWidget {
|
|||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
// We want to size to the shortest side
|
// We want to size to the shortest side
|
||||||
return [
|
return [
|
||||||
Align(
|
Transform.translate(
|
||||||
alignment: Alignment(0, config.shortMode ? 1 : 0),
|
offset: Offset(0, 20),
|
||||||
child: Transform.translate(
|
child: IllustrationPiece(
|
||||||
offset: Offset(0, config.shortMode ? 30 : 0),
|
fileName: 'chichen.png',
|
||||||
child: FractionallySizedBox(
|
heightFactor: .55,
|
||||||
heightFactor: config.shortMode ? 1 : .6,
|
minHeight: 400,
|
||||||
child: WonderHero(
|
zoomAmt: .05,
|
||||||
config,
|
enableHero: true,
|
||||||
'chichen-mg',
|
|
||||||
child: Image.asset('$assetPath/chichen.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Stack(
|
IllustrationPiece(
|
||||||
children: [
|
fileName: 'foreground-left.png',
|
||||||
Transform.scale(
|
alignment: Alignment.bottomCenter,
|
||||||
scale: 1 + config.zoom * .05,
|
initialScale: .9,
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(-40, 60),
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
heightFactor: .65,
|
||||||
child: BottomLeft(
|
fractionalOffset: Offset(-.4, .2),
|
||||||
child: SizedBox(
|
zoomAmt: .25,
|
||||||
height: 500,
|
dynamicHzOffset: -250,
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.4, .15),
|
|
||||||
child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-right.png',
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
initialScale: .95,
|
||||||
|
heightFactor: .6,
|
||||||
|
fractionalOffset: Offset(.4, .2),
|
||||||
|
zoomAmt: .1,
|
||||||
|
dynamicHzOffset: 250,
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'top-left.png',
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
initialScale: .9,
|
||||||
|
initialOffset: Offset(-40, 60),
|
||||||
|
heightFactor: .75,
|
||||||
|
fractionalOffset: Offset(-.5, -.3),
|
||||||
|
zoomAmt: .25,
|
||||||
|
dynamicHzOffset: 100,
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'top-right.png',
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
initialScale: .95,
|
||||||
|
heightFactor: .85,
|
||||||
|
fractionalOffset: Offset(.4, -.4),
|
||||||
|
zoomAmt: .1,
|
||||||
|
dynamicHzOffset: -100,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Transform.scale(
|
// Stack(
|
||||||
scale: 1 + config.zoom * .03,
|
// children: [
|
||||||
child: FractionalTranslation(
|
// Transform.scale(
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
// scale: 1 + config.zoom * .05,
|
||||||
child: BottomRight(
|
// child: FractionalTranslation(
|
||||||
child: SizedBox(
|
// translation: Offset(-.2 * (1 - curvedAnim), 0),
|
||||||
height: 350,
|
// child: BottomLeft(
|
||||||
child: FractionalTranslation(
|
// child: SizedBox(
|
||||||
translation: Offset(.35, .2),
|
// height: 500,
|
||||||
child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.cover),
|
// child: FractionalTranslation(
|
||||||
),
|
// translation: Offset(-.4, .15),
|
||||||
),
|
// child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.cover),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Transform.scale(
|
// ),
|
||||||
scale: 1 + config.zoom * .25,
|
// ),
|
||||||
child: FractionalTranslation(
|
// Transform.scale(
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
// scale: 1 + config.zoom * .03,
|
||||||
child: TopLeft(
|
// child: FractionalTranslation(
|
||||||
child: SizedBox(
|
// translation: Offset(.2 * (1 - curvedAnim), 0),
|
||||||
height: 600,
|
// child: BottomRight(
|
||||||
child: FractionalTranslation(
|
// child: SizedBox(
|
||||||
translation: Offset(-.3, -.45),
|
// height: 350,
|
||||||
child: Image.asset('$assetPath/top-left.png', opacity: anim, fit: BoxFit.cover),
|
// child: FractionalTranslation(
|
||||||
),
|
// translation: Offset(.35, .2),
|
||||||
),
|
// child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.cover),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Transform.scale(
|
// ),
|
||||||
scale: 1 + config.zoom * .2,
|
// ),
|
||||||
child: FractionalTranslation(
|
// Transform.scale(
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
// scale: 1 + config.zoom * .25,
|
||||||
child: TopRight(
|
// child: FractionalTranslation(
|
||||||
child: SizedBox(
|
// translation: Offset(-.2 * (1 - curvedAnim), 0),
|
||||||
height: 700,
|
// child: TopLeft(
|
||||||
child: FractionalTranslation(
|
// child: SizedBox(
|
||||||
translation: Offset(.2, -.35),
|
// height: 600,
|
||||||
child: Image.asset('$assetPath/top-right.png', opacity: anim, fit: BoxFit.cover),
|
// child: FractionalTranslation(
|
||||||
),
|
// translation: Offset(-.3, -.45),
|
||||||
),
|
// child: Image.asset('$assetPath/top-left.png', opacity: anim, fit: BoxFit.cover),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ),
|
||||||
),
|
// ),
|
||||||
|
// Transform.scale(
|
||||||
|
// scale: 1 + config.zoom * .2,
|
||||||
|
// child: FractionalTranslation(
|
||||||
|
// translation: Offset(.2 * (1 - curvedAnim), 0),
|
||||||
|
// child: TopRight(
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 700,
|
||||||
|
// child: FractionalTranslation(
|
||||||
|
// translation: Offset(.2, -.35),
|
||||||
|
// child: Image.asset('$assetPath/top-right.png', opacity: anim, fit: BoxFit.cover),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -18,6 +18,7 @@ class ChristRedeemerIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.christRedeemer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,90 +33,52 @@ class ChristRedeemerIllustration extends StatelessWidget {
|
|||||||
opacity: anim.drive(Tween(begin: 0, end: .4)),
|
opacity: anim.drive(Tween(begin: 0, end: .4)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: config.shortMode ? Alignment(.5, -1.5) : Alignment(.5, -.75),
|
fileName: 'sun.png',
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(0, 20),
|
||||||
translation: Offset(0, .5 * anim.value),
|
enableHero: true,
|
||||||
child: WonderHero(
|
heightFactor: .2,
|
||||||
config,
|
minHeight: 120,
|
||||||
'christ-sun',
|
fractionalOffset: Offset(.5, -1),
|
||||||
child: Transform.scale(
|
|
||||||
scale: config.shortMode ? 1.4 : 1.6,
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/sun.png',
|
|
||||||
cacheWidth: context.widthPx.round() * 2,
|
|
||||||
opacity: anim,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
return [
|
return [
|
||||||
ClipRect(
|
IllustrationPiece(
|
||||||
child: Transform.scale(
|
fileName: 'redeemer.png',
|
||||||
scale: 1 + config.zoom * .2,
|
enableHero: true,
|
||||||
child: FractionalTranslation(
|
heightFactor: 1,
|
||||||
translation: Offset(0, config.shortMode ? .5 : .2),
|
alignment: Alignment.bottomCenter,
|
||||||
child: BottomCenter(
|
fractionalOffset: Offset(0, .1),
|
||||||
child: FractionallySizedBox(
|
zoomAmt: .1,
|
||||||
heightFactor: config.shortMode ? 1.5 : 1.2,
|
|
||||||
child: WonderHero(
|
|
||||||
config,
|
|
||||||
'christ-mg',
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/redeemer.png',
|
|
||||||
opacity: anim,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
//
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Stack(
|
IllustrationPiece(
|
||||||
children: [
|
fileName: 'foreground-left.png',
|
||||||
Transform.scale(
|
alignment: Alignment.bottomCenter,
|
||||||
scale: 1 + config.zoom * .15,
|
initialScale: .9,
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(-40, 60),
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
heightFactor: .55,
|
||||||
child: BottomLeft(
|
fractionalOffset: Offset(-.25, 0),
|
||||||
child: FractionallySizedBox(
|
zoomAmt: .25,
|
||||||
widthFactor: 1.5,
|
dynamicHzOffset: -100,
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.25, .03),
|
|
||||||
child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
),
|
||||||
),
|
IllustrationPiece(
|
||||||
),
|
fileName: 'foreground-right.png',
|
||||||
),
|
alignment: Alignment.bottomCenter,
|
||||||
),
|
initialOffset: Offset(20, 40),
|
||||||
Transform.scale(
|
initialScale: .95,
|
||||||
scale: 1 + config.zoom * .3,
|
heightFactor: .65,
|
||||||
child: FractionalTranslation(
|
fractionalOffset: Offset(.2, 0),
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
zoomAmt: .1,
|
||||||
child: BottomRight(
|
dynamicHzOffset: 100,
|
||||||
child: FractionallySizedBox(
|
|
||||||
widthFactor: 1.5,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.3, .2),
|
|
||||||
child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
@ -18,6 +19,7 @@ class ColosseumIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.colosseum,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,25 +57,12 @@ class ColosseumIllustration extends StatelessWidget {
|
|||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
return [
|
return [
|
||||||
Stack(
|
Stack(
|
||||||
children: [
|
children: const [
|
||||||
if (config.shortMode) ...[
|
IllustrationPiece(
|
||||||
FractionalTranslation(
|
fileName: 'colosseum.png',
|
||||||
translation: Offset(0, .9),
|
heightFactor: .55,
|
||||||
child: Container(color: bgColor),
|
minHeight: 400,
|
||||||
)
|
zoomAmt: .15,
|
||||||
],
|
|
||||||
Center(
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(0, config.shortMode ? .1 : -.15),
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: config.shortMode ? .85 : 1.55 + config.zoom * .2,
|
|
||||||
child: WonderHero(
|
|
||||||
config,
|
|
||||||
'colosseum-mg',
|
|
||||||
child: Image.asset('$assetPath/colosseum.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -81,40 +70,27 @@ class ColosseumIllustration extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Stack(children: [
|
IllustrationPiece(
|
||||||
BottomLeft(
|
fileName: 'foreground-left.png',
|
||||||
child: FractionallySizedBox(
|
alignment: Alignment.bottomCenter,
|
||||||
heightFactor: .56,
|
initialScale: .9,
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(-40, 60),
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
heightFactor: .65,
|
||||||
child: Transform.scale(
|
fractionalOffset: Offset(-.5, .1),
|
||||||
scale: 1 + config.zoom * .3,
|
zoomAmt: .25,
|
||||||
child: FractionalTranslation(
|
dynamicHzOffset: -150,
|
||||||
translation: Offset(-.1, .1),
|
|
||||||
child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-right.png',
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
initialScale: .95,
|
||||||
|
heightFactor: .75,
|
||||||
|
fractionalOffset: Offset(.5, .25),
|
||||||
|
zoomAmt: .1,
|
||||||
|
dynamicHzOffset: 150,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BottomRight(
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
heightFactor: .56,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 1 + config.zoom * .3,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.3, .2),
|
|
||||||
child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
|
||||||
|
|
||||||
/// Combines [Align], [FractionalBoxWithMinSize], [Image] and [Transform.translate]
|
|
||||||
/// to standardize behavior across the various wonder illustrations
|
|
||||||
class IllustrationPiece extends StatelessWidget {
|
|
||||||
const IllustrationPiece({
|
|
||||||
Key? key,
|
|
||||||
required this.type,
|
|
||||||
required this.anim,
|
|
||||||
required this.fileName,
|
|
||||||
required this.heightFactor,
|
|
||||||
this.alignment = Alignment.center,
|
|
||||||
this.minHeight,
|
|
||||||
this.translation,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final WonderType type;
|
|
||||||
final Animation<double> anim;
|
|
||||||
final double heightFactor;
|
|
||||||
final String fileName;
|
|
||||||
final Offset? translation;
|
|
||||||
final Alignment alignment;
|
|
||||||
final double? minHeight;
|
|
||||||
final BoxFit boxFit = BoxFit.cover;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Align(
|
|
||||||
alignment: alignment,
|
|
||||||
child: Transform.translate(
|
|
||||||
offset: translation ?? Offset.zero,
|
|
||||||
child: FractionalBoxWithMinSize(
|
|
||||||
heightFactor: heightFactor,
|
|
||||||
minHeight: minHeight ?? 0,
|
|
||||||
child: Image.asset('${type.assetPath}/$fileName', opacity: anim, fit: boxFit),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// class IllustrationPieceStack extends StatelessWidget {
|
|
||||||
// const IllustrationPieceStack({Key? key, required this.pieces}) : super(key: key);
|
|
||||||
// final List<IllustrationPiece> pieces;
|
|
||||||
//
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context) {
|
|
||||||
// return Stack(
|
|
||||||
// children: pieces,
|
|
||||||
// // [
|
|
||||||
// // BottomCenter(
|
|
||||||
// // child: Transform.translate(
|
|
||||||
// // offset: Offset(context.widthPx * .05, 0),
|
|
||||||
// // child: FractionalBoxWithMinSize(
|
|
||||||
// // heightFactor: backHeightFactor,
|
|
||||||
// // minHeight: 300,
|
|
||||||
// // child: Image.asset(
|
|
||||||
// // '${type.assetPath}/foreground-back.png',
|
|
||||||
// // opacity: anim,
|
|
||||||
// // fit: BoxFit.cover,
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // BottomCenter(
|
|
||||||
// // child: Transform.translate(
|
|
||||||
// // offset: Offset(-context.widthPx * .1, 0),
|
|
||||||
// // child: FractionalBoxWithMinSize(
|
|
||||||
// // heightFactor: frontHeightFactor,
|
|
||||||
// // minHeight: 300,
|
|
||||||
// // child: Image.asset(
|
|
||||||
// // '${type.assetPath}/foreground-front.png',
|
|
||||||
// // opacity: anim,
|
|
||||||
// // fit: BoxFit.cover,
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // )
|
|
||||||
//
|
|
||||||
// // BottomCenter(
|
|
||||||
// // child: Transform.scale(
|
|
||||||
// // scale: 1 + config.zoom * .05,
|
|
||||||
// // child: FractionallySizedBox(
|
|
||||||
// // heightFactor: backHeightFactor,
|
|
||||||
// // child: FractionalTranslation(
|
|
||||||
// // translation: Offset(.1, 0),
|
|
||||||
// // child: Image.asset('${type.assetPath}/foreground-back.png', opacity: anim, fit: BoxFit.cover)),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // BottomCenter(
|
|
||||||
// // child: Transform.scale(
|
|
||||||
// // scale: 1 + config.zoom * .2,
|
|
||||||
// // child: FractionallySizedBox(
|
|
||||||
// // heightFactor: frontHeightFactor,
|
|
||||||
// // child: FractionalTranslation(
|
|
||||||
// // translation: Offset(-.2, 0),
|
|
||||||
// // child: Image.asset('${type.assetPath}/foreground-front.png', opacity: anim, fit: BoxFit.cover)),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ],
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Encapsulates a common behavior where
|
|
||||||
/// - we want something to be fractionally sized, down to a pt...
|
|
||||||
/// - when we hit a minSize, stop reducing in size...
|
|
||||||
/// - until available space is less < minSize, then allow piece to reduce
|
|
||||||
/// eg, Take a piece with 50% height, and 500px minHeight. As available height is reduced it will attempt to use 50% height,
|
|
||||||
/// At 200px it it will stop reducing itself in height and ignore the fractional sizing.
|
|
||||||
/// One the available height is < 200px, the piece will then reduce itself so it still
|
|
||||||
/// fits on screen without being clipped.
|
|
||||||
class FractionalBoxWithMinSize extends StatelessWidget {
|
|
||||||
const FractionalBoxWithMinSize(
|
|
||||||
{Key? key, this.minWidth, this.minHeight, this.widthFactor, this.heightFactor, required this.child})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final double? widthFactor;
|
|
||||||
final double? heightFactor;
|
|
||||||
final double? minWidth;
|
|
||||||
final double? minHeight;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert((widthFactor == null && minWidth == null) || (widthFactor != null && minWidth != null),
|
|
||||||
'widthFactor and minWidth must be provided together');
|
|
||||||
assert((heightFactor == null && minHeight == null) || (heightFactor != null && minHeight != null),
|
|
||||||
'heightFactor and minWidth must be provided together');
|
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
|
||||||
var c = child;
|
|
||||||
if (widthFactor != null) {
|
|
||||||
double size = max(minWidth!, widthFactor! * constraints.maxWidth);
|
|
||||||
c = SizedBox(width: size, child: c);
|
|
||||||
}
|
|
||||||
if (heightFactor != null) {
|
|
||||||
double size = max(minHeight!, heightFactor! * constraints.maxHeight);
|
|
||||||
c = SizedBox(height: size, child: c);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
|
||||||
|
|
||||||
/// TODO: This can just be an IllustrrationPiece
|
|
||||||
/// TODO: Add counter scaling to illustration piece like this
|
|
||||||
/// TODO: Add hero support to [IllustrationPiece]? Or at least use [FractionalBoxWithMinSize]
|
|
||||||
class IllustrationMg extends StatelessWidget {
|
|
||||||
const IllustrationMg(
|
|
||||||
this.imagePath, {
|
|
||||||
Key? key,
|
|
||||||
required this.config,
|
|
||||||
required this.anim,
|
|
||||||
required this.type,
|
|
||||||
required this.heightFraction,
|
|
||||||
this.maxHeight = 700,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String imagePath;
|
|
||||||
final WonderIllustrationConfig config;
|
|
||||||
final Animation<double> anim;
|
|
||||||
final WonderType type;
|
|
||||||
final double maxHeight;
|
|
||||||
final double heightFraction;
|
|
||||||
String get assetPath => type.assetPath;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.only(top: $styles.insets.sm),
|
|
||||||
child: LayoutBuilder(builder: (_, constraints) {
|
|
||||||
final height = min(maxHeight, constraints.maxHeight) * heightFraction;
|
|
||||||
return Center(
|
|
||||||
child: WonderHero(
|
|
||||||
config,
|
|
||||||
'$imagePath-hero',
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 4 + config.zoom * .5,
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/$imagePath',
|
|
||||||
opacity: anim,
|
|
||||||
height: height * .25,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
144
lib/ui/wonder_illustrations/common/illustration_piece.dart
Normal file
144
lib/ui/wonder_illustrations/common/illustration_piece.dart
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import 'package:wonders/common_libs.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
|
|
||||||
|
/// Combines [Align], [FractionalBoxWithMinSize], [Image] and [Transform.translate]
|
||||||
|
/// to standardize behavior across the various wonder illustrations
|
||||||
|
class IllustrationPiece extends StatefulWidget {
|
||||||
|
const IllustrationPiece({
|
||||||
|
Key? key,
|
||||||
|
required this.fileName,
|
||||||
|
required this.heightFactor,
|
||||||
|
this.alignment = Alignment.center,
|
||||||
|
this.minHeight,
|
||||||
|
this.offset = Offset.zero,
|
||||||
|
this.fractionalOffset,
|
||||||
|
this.zoomAmt = 0,
|
||||||
|
this.initialOffset = Offset.zero,
|
||||||
|
this.boxFit = BoxFit.fitHeight,
|
||||||
|
this.overflow = true,
|
||||||
|
this.enableHero = false,
|
||||||
|
this.initialScale = 1,
|
||||||
|
this.dynamicHzOffset = 0,
|
||||||
|
this.top,
|
||||||
|
this.bottom,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String fileName;
|
||||||
|
|
||||||
|
final Alignment alignment;
|
||||||
|
|
||||||
|
/// Will animate from this position to Offset.zero, eg is value is Offset(0, 100), the piece will slide up vertically 100px as it enters the screen
|
||||||
|
final Offset initialOffset;
|
||||||
|
|
||||||
|
/// Will animate from this scale to 1, eg if scale is .7, the piece will scale from .7 to 1.0 as it enters the screen.
|
||||||
|
final double initialScale;
|
||||||
|
|
||||||
|
/// % height, will be overridden by minHeight
|
||||||
|
final double heightFactor;
|
||||||
|
|
||||||
|
/// min height in pixels, piece will not be allowed to go below this height in px, unless it has to (available height is too small)
|
||||||
|
final double? minHeight;
|
||||||
|
|
||||||
|
/// px offset for this piece
|
||||||
|
final Offset offset;
|
||||||
|
|
||||||
|
/// offset based on a fraction of the piece size
|
||||||
|
final Offset? fractionalOffset;
|
||||||
|
|
||||||
|
/// The % amount that this object should scale up as the user drags their finger up the screen
|
||||||
|
final double zoomAmt;
|
||||||
|
|
||||||
|
/// Applied to the underlying image in the piece, defaults to [BoxFit.cover]
|
||||||
|
final BoxFit boxFit;
|
||||||
|
|
||||||
|
/// Whether or not this piece can overflow it's parent on the horizontal bounds
|
||||||
|
final bool overflow;
|
||||||
|
|
||||||
|
/// Adds a hero tag to this piece, made from wonderType + fileName
|
||||||
|
final bool enableHero;
|
||||||
|
|
||||||
|
/// Max px offset of the piece as the screen size grows horizontally
|
||||||
|
final double dynamicHzOffset;
|
||||||
|
|
||||||
|
final Widget Function(BuildContext context)? top;
|
||||||
|
final Widget Function(BuildContext context)? bottom;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<IllustrationPiece> createState() => _IllustrationPieceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IllustrationPieceState extends State<IllustrationPiece> {
|
||||||
|
double? aspectRatio;
|
||||||
|
ui.Image? uiImage;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final wonderBuilder = context.watch<WonderIllustrationBuilderState>();
|
||||||
|
final type = wonderBuilder.widget.wonderType;
|
||||||
|
final imgPath = '${type.assetPath}/${widget.fileName}';
|
||||||
|
if (aspectRatio == null) {
|
||||||
|
aspectRatio == 0; // indicates load has started, so we don't run twice
|
||||||
|
rootBundle.load(imgPath).then((img) async {
|
||||||
|
uiImage = await decodeImageFromList(img.buffer.asUint8List());
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() => aspectRatio = uiImage!.width / uiImage!.height);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Align(
|
||||||
|
alignment: widget.alignment,
|
||||||
|
child: LayoutBuilder(
|
||||||
|
key: ValueKey(aspectRatio),
|
||||||
|
builder: (_, constraints) {
|
||||||
|
final anim = wonderBuilder.anim;
|
||||||
|
final curvedAnim = Curves.easeOut.transform(anim.value);
|
||||||
|
final config = wonderBuilder.widget.config;
|
||||||
|
Widget img = Image.asset(imgPath, opacity: anim, fit: widget.boxFit);
|
||||||
|
if (widget.overflow) {
|
||||||
|
img = OverflowBox(maxWidth: 2000, child: img);
|
||||||
|
}
|
||||||
|
final double introZoom = (widget.initialScale - 1) * (1 - curvedAnim);
|
||||||
|
|
||||||
|
/// Determine target height
|
||||||
|
final double height = max(widget.minHeight ?? 0, constraints.maxHeight * widget.heightFactor);
|
||||||
|
|
||||||
|
/// Combine all the translations, initial + offset + dynamicHzOffset + fractionalOffset
|
||||||
|
Offset finalTranslation = widget.offset;
|
||||||
|
// Initial
|
||||||
|
if (widget.initialOffset != Offset.zero) {
|
||||||
|
finalTranslation += widget.initialOffset * (1 - curvedAnim);
|
||||||
|
}
|
||||||
|
// Dynamic
|
||||||
|
final dynamicOffsetAmt = min(context.widthPx / 1500, 1);
|
||||||
|
finalTranslation += Offset(dynamicOffsetAmt * widget.dynamicHzOffset, 0);
|
||||||
|
// Fractional
|
||||||
|
final width = height * (aspectRatio ?? 0);
|
||||||
|
if (widget.fractionalOffset != null) {
|
||||||
|
finalTranslation += Offset(
|
||||||
|
widget.fractionalOffset!.dx * width,
|
||||||
|
height * widget.fractionalOffset!.dy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
if (widget.bottom != null) Positioned.fill(child: widget.bottom!.call(context)),
|
||||||
|
if (uiImage != null) ...[
|
||||||
|
Transform.translate(
|
||||||
|
offset: finalTranslation,
|
||||||
|
child: Transform.scale(
|
||||||
|
scale: 1 + (widget.zoomAmt * config.zoom) + introZoom,
|
||||||
|
child: SizedBox(
|
||||||
|
height: height,
|
||||||
|
width: height * aspectRatio!,
|
||||||
|
child: !widget.enableHero ? img : Hero(tag: '$type-${widget.fileName}', child: img),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (widget.top != null) Positioned.fill(child: widget.top!.call(context)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/illustration_mg.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -20,6 +19,7 @@ class GreatWallIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.greatWall,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,104 +34,51 @@ class GreatWallIllustration extends StatelessWidget {
|
|||||||
opacity: anim.drive(Tween(begin: 0, end: .5)),
|
opacity: anim.drive(Tween(begin: 0, end: .5)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: config.shortMode ? Alignment(-.5, -.5) : Alignment(-.45, -.63),
|
fileName: 'sun.png',
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(0, 20),
|
||||||
translation: Offset(0, -.5 * anim.value),
|
enableHero: true,
|
||||||
child: WonderHero(
|
heightFactor: .15,
|
||||||
config,
|
minHeight: 150,
|
||||||
'great-wall-sun',
|
offset: config.shortMode ? Offset(-70, context.heightPx * -.05) : Offset(-150, context.heightPx * -.25),
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/sun.png',
|
|
||||||
cacheWidth: context.widthPx.round() * 2,
|
|
||||||
width: config.shortMode ? 100 : 150,
|
|
||||||
opacity: anim,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
return [
|
return [
|
||||||
IllustrationMg(
|
IllustrationPiece(
|
||||||
'great-wall.png',
|
fileName: 'great-wall.png',
|
||||||
type: WonderType.greatWall,
|
heightFactor: .55,
|
||||||
anim: anim,
|
minHeight: 600,
|
||||||
config: config,
|
zoomAmt: .05,
|
||||||
maxHeight: 800,
|
enableHero: true,
|
||||||
heightFraction: .85,
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
return [
|
|
||||||
Center(
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(0, config.shortMode ? .1 * anim.value : 0),
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
widthFactor: config.shortMode ? null : 1.3,
|
|
||||||
child: WonderHero(
|
|
||||||
config,
|
|
||||||
'great-wall-mg',
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/great-wall.png',
|
|
||||||
opacity: anim,
|
|
||||||
width: config.shortMode ? 300 : 500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// child: FractionalTranslation(
|
|
||||||
// translation: Offset(0, 0),
|
|
||||||
// child: Transform.scale(
|
|
||||||
// scale: 1, //config.shortMode ? .95 : 1.4 + config.zoom * .2,
|
|
||||||
// child: WonderHero(
|
|
||||||
// config,
|
|
||||||
// 'great-wall-mg',
|
|
||||||
// child: Image.asset(
|
|
||||||
// '$assetPath/great-wall.png',
|
|
||||||
// opacity: anim,
|
|
||||||
// width: 700,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Stack(children: [
|
IllustrationPiece(
|
||||||
BottomRight(
|
fileName: 'foreground-left.png',
|
||||||
child: FractionalTranslation(
|
alignment: Alignment.bottomCenter,
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
initialScale: .9,
|
||||||
child: Transform.scale(
|
initialOffset: Offset(-40, 60),
|
||||||
scale: 1.5 + config.zoom * .1,
|
heightFactor: .75,
|
||||||
child: FractionalTranslation(
|
fractionalOffset: Offset(-.4, .45),
|
||||||
translation: Offset(.46, -.22),
|
zoomAmt: .25,
|
||||||
child: Image.asset('$assetPath/foreground-right.png',
|
dynamicHzOffset: -150,
|
||||||
opacity: anim, cacheWidth: context.widthPx.round() * 3),
|
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-right.png',
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
initialScale: .95,
|
||||||
|
heightFactor: .85,
|
||||||
|
fractionalOffset: Offset(.4, .25),
|
||||||
|
zoomAmt: .1,
|
||||||
|
dynamicHzOffset: 150,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
BottomLeft(
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 1 + config.zoom * .3,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.3, -.01),
|
|
||||||
child: Image.asset('$assetPath/foreground-left.png',
|
|
||||||
opacity: anim, cacheWidth: context.widthPx.round() * 3),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ class MachuPicchuIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.machuPicchu,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,80 +34,49 @@ class MachuPicchuIllustration extends StatelessWidget {
|
|||||||
opacity: anim.drive(Tween(begin: 0, end: .7)),
|
opacity: anim.drive(Tween(begin: 0, end: .7)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: config.shortMode ? Alignment.center : Alignment(.75, -.6),
|
fileName: 'sun.png',
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(0, 20),
|
||||||
translation: Offset(0, -.5 * anim.value),
|
enableHero: true,
|
||||||
child: Transform.scale(
|
heightFactor: .15,
|
||||||
scale: config.shortMode ? .75 : 1,
|
minHeight: 150,
|
||||||
child: WonderHero(
|
offset: config.shortMode ? Offset(-70, context.heightPx * -.05) : Offset(-150, context.heightPx * -.25),
|
||||||
config,
|
|
||||||
'machu-sun',
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/sun.png',
|
|
||||||
cacheWidth: context.widthPx.round() * 2,
|
|
||||||
opacity: anim,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) => [
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) => [
|
||||||
Center(
|
IllustrationPiece(
|
||||||
child: Transform.scale(
|
fileName: 'machu-picchu.png',
|
||||||
scale: config.shortMode ? 1.2 : 2.5 + config.zoom * .2,
|
heightFactor: .65,
|
||||||
alignment: Alignment(config.shortMode ? 0 : .15, config.shortMode ? -0.6 : .3),
|
minHeight: 500,
|
||||||
child: WonderHero(
|
zoomAmt: .05,
|
||||||
config,
|
enableHero: true,
|
||||||
'machu-mg',
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/machu-picchu.png',
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
opacity: anim,
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Transform.translate(
|
IllustrationPiece(
|
||||||
offset: Offset(0, 20 * (1 - curvedAnim)),
|
fileName: 'foreground-back.png',
|
||||||
child: Stack(children: [
|
alignment: Alignment.bottomCenter,
|
||||||
BottomRight(
|
initialScale: .9,
|
||||||
child: Transform.scale(
|
initialOffset: Offset(0, 60),
|
||||||
scale: 1 + config.zoom * .05,
|
heightFactor: .6,
|
||||||
child: FractionallySizedBox(
|
fractionalOffset: Offset(0, .3),
|
||||||
widthFactor: 1.5,
|
zoomAmt: .1,
|
||||||
child: FractionalTranslation(
|
dynamicHzOffset: 150,
|
||||||
translation: Offset(0, .1),
|
|
||||||
child: Image.asset('$assetPath/foreground-back.png', opacity: anim),
|
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-front.png',
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
heightFactor: .5,
|
||||||
|
initialScale: .95,
|
||||||
|
fractionalOffset: Offset(-.25, .25),
|
||||||
|
zoomAmt: .12,
|
||||||
|
dynamicHzOffset: -50,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
BottomLeft(
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 1 + config.zoom * .25,
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
widthFactor: 1.5,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.3, .4),
|
|
||||||
child: Image.asset('$assetPath/foreground-front.png', opacity: anim),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ class PetraIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.petra,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,74 +34,69 @@ class PetraIllustration extends StatelessWidget {
|
|||||||
opacity: anim.drive(Tween(begin: 0, end: .25)),
|
opacity: anim.drive(Tween(begin: 0, end: .25)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: Alignment(-.3, config.shortMode ? -1.5 : -1.23),
|
fileName: 'moon.png',
|
||||||
child: FractionalTranslation(
|
heightFactor: .15,
|
||||||
translation: Offset(0, .5 * anim.value),
|
minHeight: 100,
|
||||||
child: WonderHero(
|
alignment: Alignment.topCenter,
|
||||||
config,
|
fractionalOffset: Offset(-.7, 0),
|
||||||
'petra-moon',
|
|
||||||
child: Image.asset(
|
|
||||||
'$assetPath/moon.png',
|
|
||||||
opacity: anim,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) => [
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) => [
|
||||||
Center(
|
FractionallySizedBox(
|
||||||
child: FractionalTranslation(
|
heightFactor: config.shortMode ? 1 : .8,
|
||||||
translation: Offset(0, config.shortMode ? 0.05 : -.1),
|
alignment: Alignment.bottomCenter,
|
||||||
child: FractionallySizedBox(
|
child: IllustrationPiece(
|
||||||
widthFactor: config.shortMode ? 1 : 2,
|
fileName: 'petra.png',
|
||||||
child: WonderHero(
|
heightFactor: .65,
|
||||||
config,
|
minHeight: 500,
|
||||||
'petra-mg',
|
zoomAmt: .1,
|
||||||
child: Image.asset('$assetPath/petra.png', fit: BoxFit.contain, opacity: anim),
|
enableHero: true,
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
Stack(children: [
|
IllustrationPiece(
|
||||||
CenterLeft(
|
fileName: 'foreground-left.png',
|
||||||
child: FractionallySizedBox(
|
alignment: Alignment.bottomCenter,
|
||||||
widthFactor: .63,
|
initialOffset: Offset(-80, 0),
|
||||||
child: FractionalTranslation(
|
heightFactor: 1,
|
||||||
translation: Offset(-.3 * (1 - curvedAnim), 0),
|
fractionalOffset: Offset(-.5, 0),
|
||||||
child: Transform.scale(
|
zoomAmt: .1,
|
||||||
scale: 1.1 + config.zoom * .2,
|
dynamicHzOffset: -130,
|
||||||
child: FractionalTranslation(
|
bottom: (_) {
|
||||||
translation: Offset(-.35, -.07),
|
/// To cover everything behind this piece with a solid color, we scale up a container
|
||||||
child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.contain),
|
/// and then offset it in negative space
|
||||||
|
const double scaleX = 5;
|
||||||
|
return FractionalTranslation(
|
||||||
|
translation: Offset(-1 - scaleX / 2, 0),
|
||||||
|
child:
|
||||||
|
Transform.scale(scaleX: 5, child: Container(color: WonderType.petra.fgColor.withOpacity(anim.value))),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-right.png',
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(80, 00),
|
||||||
|
heightFactor: 1,
|
||||||
|
fractionalOffset: Offset(.5, 0),
|
||||||
|
zoomAmt: .15,
|
||||||
|
dynamicHzOffset: 130,
|
||||||
|
bottom: (_) {
|
||||||
|
/// To cover everything behind this piece with a solid color, we scale up a container and then offset it in negative space
|
||||||
|
const double scaleX = 5;
|
||||||
|
return FractionalTranslation(
|
||||||
|
translation: Offset(1 + scaleX / 2, 0),
|
||||||
|
child:
|
||||||
|
Transform.scale(scaleX: 5, child: Container(color: WonderType.petra.fgColor.withOpacity(anim.value))),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
CenterRight(
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
widthFactor: .72,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.3 * (1 - curvedAnim), 0),
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 1 + config.zoom * .4,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.4, -.03),
|
|
||||||
child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.contain),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/illustration_fg.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/illustration_mg.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -17,6 +15,7 @@ class PyramidsGizaIllustration extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WonderIllustrationBuilder(
|
return WonderIllustrationBuilder(
|
||||||
|
wonderType: WonderType.pyramidsGiza,
|
||||||
config: config,
|
config: config,
|
||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
@ -35,93 +34,54 @@ class PyramidsGizaIllustration extends StatelessWidget {
|
|||||||
flipY: true,
|
flipY: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: Alignment(.75, config.shortMode ? -.2 : -.5),
|
fileName: 'moon.png',
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(0, 20),
|
||||||
translation: Offset(0, -.5 * anim.value),
|
enableHero: true,
|
||||||
child: WonderHero(
|
heightFactor: .15,
|
||||||
config,
|
minHeight: 100,
|
||||||
'pyramids-moon',
|
offset: config.shortMode ? Offset(100, context.heightPx * -.1) : Offset(150, context.heightPx * -.15),
|
||||||
child: Transform.scale(
|
zoomAmt: .05,
|
||||||
scale: config.shortMode ? 0.8 : 1.2,
|
|
||||||
child: Image.asset('$assetPath/moon.png', opacity: anim),
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
return [
|
return [
|
||||||
IllustrationMg(
|
IllustrationPiece(
|
||||||
'pyramids.png',
|
fileName: 'pyramids.png',
|
||||||
type: WonderType.pyramidsGiza,
|
enableHero: true,
|
||||||
anim: anim,
|
heightFactor: .5,
|
||||||
config: config,
|
minHeight: 300,
|
||||||
maxHeight: 600,
|
zoomAmt: .1,
|
||||||
heightFraction: .85,
|
boxFit: BoxFit.contain,
|
||||||
),
|
overflow: !config.shortMode,
|
||||||
|
)
|
||||||
// Align(
|
|
||||||
// alignment: Alignment(0, config.shortMode ? 0.9 : 0),
|
|
||||||
// child: WonderHero(config, 'pyramids-mg',
|
|
||||||
// child: Transform.scale(
|
|
||||||
// scale: 1 + config.zoom * .1,
|
|
||||||
// child: FractionallySizedBox(
|
|
||||||
// widthFactor: config.shortMode ? 1 : 1.94,
|
|
||||||
// child: Image.asset('$assetPath/pyramids.png', fit: BoxFit.contain, opacity: anim),
|
|
||||||
// ),
|
|
||||||
// )),
|
|
||||||
// ),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
IllustrationPiece(
|
IllustrationPiece(
|
||||||
type: WonderType.pyramidsGiza,
|
|
||||||
anim: anim,
|
|
||||||
fileName: 'foreground-back.png',
|
fileName: 'foreground-back.png',
|
||||||
heightFactor: .5,
|
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
|
initialOffset: Offset(20, 40),
|
||||||
|
initialScale: .95,
|
||||||
|
heightFactor: .55,
|
||||||
|
fractionalOffset: Offset(.1, .06),
|
||||||
|
zoomAmt: .1,
|
||||||
|
dynamicHzOffset: 150,
|
||||||
),
|
),
|
||||||
IllustrationPiece(
|
IllustrationPiece(
|
||||||
type: WonderType.pyramidsGiza,
|
|
||||||
anim: anim,
|
|
||||||
fileName: 'foreground-front.png',
|
fileName: 'foreground-front.png',
|
||||||
heightFactor: .5,
|
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
)
|
initialScale: .9,
|
||||||
// Transform.scale(
|
initialOffset: Offset(-40, 60),
|
||||||
// scale: 1 + config.zoom * .2,
|
heightFactor: .55,
|
||||||
// child: Transform.translate(
|
fractionalOffset: Offset(-.1, .1),
|
||||||
// offset: Offset(0, 10 * (1 - curvedAnim)),
|
zoomAmt: .25,
|
||||||
// child: BottomCenter(
|
dynamicHzOffset: -150,
|
||||||
// child: FractionallySizedBox(
|
),
|
||||||
// widthFactor: 1.2,
|
|
||||||
// child: FractionalTranslation(
|
|
||||||
// translation: Offset(0, -1.2),
|
|
||||||
// child: Image.asset('$assetPath/foreground-back.png', opacity: anim, fit: BoxFit.cover)),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Transform.scale(
|
|
||||||
// scale: 1 + config.zoom * .4,
|
|
||||||
// child: Transform.translate(
|
|
||||||
// offset: Offset(0, 30 * (1 - curvedAnim)),
|
|
||||||
// child: BottomCenter(
|
|
||||||
// child: FractionallySizedBox(
|
|
||||||
// widthFactor: 1.52,
|
|
||||||
// child: FractionalTranslation(
|
|
||||||
// translation: Offset(0, 0.1),
|
|
||||||
// child: Image.asset('$assetPath/foreground-front.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/ui/common/fade_color_transition.dart';
|
import 'package:wonders/ui/common/fade_color_transition.dart';
|
||||||
|
import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart';
|
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
|
||||||
|
|
||||||
@ -20,11 +20,11 @@ class TajMahalIllustration extends StatelessWidget {
|
|||||||
bgBuilder: _buildBg,
|
bgBuilder: _buildBg,
|
||||||
mgBuilder: _buildMg,
|
mgBuilder: _buildMg,
|
||||||
fgBuilder: _buildFg,
|
fgBuilder: _buildFg,
|
||||||
|
wonderType: WonderType.tajMahal,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildBg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildBg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
|
||||||
return [
|
return [
|
||||||
// Bg color
|
// Bg color
|
||||||
FadeColorTransition(color: fgColor, animation: anim),
|
FadeColorTransition(color: fgColor, animation: anim),
|
||||||
@ -38,78 +38,69 @@ class TajMahalIllustration extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Sun
|
// Sun
|
||||||
Align(
|
IllustrationPiece(
|
||||||
alignment: config.shortMode ? Alignment(-1.25, -2.8) : Alignment(-1.25, -1.15),
|
fileName: 'sun.png',
|
||||||
child: FractionalTranslation(
|
initialOffset: Offset(0, 20),
|
||||||
translation: Offset(-.2 + curvedAnim * .2, .4 - curvedAnim * .2),
|
enableHero: true,
|
||||||
child: WonderHero(config, 'taj-sun', child: Image.asset('$assetPath/sun.png', opacity: anim)),
|
heightFactor: .15,
|
||||||
|
minHeight: 140,
|
||||||
|
offset: config.shortMode ? Offset(-100, context.heightPx * -.05) : Offset(-150, context.heightPx * -.15),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildMg(BuildContext context, Animation<double> anim) {
|
||||||
return [
|
return [
|
||||||
Transform.scale(
|
LayoutBuilder(builder: (_, constraints) {
|
||||||
scale: 1 + config.zoom * .1,
|
const double minHeight = 500, heightFactor = .6, poolScale = 1;
|
||||||
child: Align(
|
return Stack(
|
||||||
alignment: Alignment(0, config.shortMode ? 1 : -.15),
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
widthFactor: config.shortMode ? 1 : 1.7,
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
children: [
|
||||||
WonderHero(
|
IllustrationPiece(
|
||||||
config,
|
fileName: 'taj-mahal.png',
|
||||||
'taj-mg',
|
heightFactor: heightFactor,
|
||||||
child: Image.asset('$assetPath/taj-mahal.png', opacity: anim, fit: BoxFit.cover),
|
minHeight: minHeight,
|
||||||
|
zoomAmt: .05,
|
||||||
|
top: config.shortMode
|
||||||
|
? null
|
||||||
|
: (_) => FractionalTranslation(
|
||||||
|
translation: Offset(0, .85),
|
||||||
|
child: IllustrationPiece(
|
||||||
|
fileName: 'pool.png',
|
||||||
|
heightFactor: heightFactor * poolScale,
|
||||||
|
minHeight: minHeight * poolScale,
|
||||||
|
zoomAmt: .05,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (!config.shortMode)
|
|
||||||
FractionalTranslation(
|
|
||||||
translation: Offset(0, 1.33),
|
|
||||||
child: Image.asset('$assetPath/pool.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
),
|
}),
|
||||||
),
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
List<Widget> _buildFg(BuildContext context, Animation<double> anim) {
|
||||||
final curvedAnim = Curves.easeOut.transform(anim.value);
|
/// Let the mangos scale up as the width of the screen grows
|
||||||
|
final mangoScale = max(context.widthPx - 400, 0) / 1000;
|
||||||
return [
|
return [
|
||||||
Transform.scale(
|
IllustrationPiece(
|
||||||
scale: 1 + config.zoom * .2,
|
fileName: 'foreground-right.png',
|
||||||
child: Stack(
|
alignment: Alignment.bottomRight,
|
||||||
children: [
|
initialOffset: Offset(20, 40),
|
||||||
FractionalTranslation(
|
initialScale: .85,
|
||||||
translation: Offset(-.2 * (1 - curvedAnim), 0),
|
heightFactor: .5 + .3 * mangoScale,
|
||||||
child: BottomLeft(
|
fractionalOffset: Offset(.3, 0),
|
||||||
child: FractionallySizedBox(
|
zoomAmt: .1,
|
||||||
heightFactor: .6,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(-.4, -.04),
|
|
||||||
child: Image.asset('$assetPath/foreground-left.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
fileName: 'foreground-left.png',
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
initialScale: .9,
|
||||||
|
initialOffset: Offset(-40, 60),
|
||||||
|
heightFactor: .5 + .3 * mangoScale,
|
||||||
|
fractionalOffset: Offset(-.2, 0),
|
||||||
|
zoomAmt: .25,
|
||||||
|
dynamicHzOffset: 0,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
FractionalTranslation(
|
|
||||||
translation: Offset(.2 * (1 - curvedAnim), 0),
|
|
||||||
child: BottomRight(
|
|
||||||
child: FractionallySizedBox(
|
|
||||||
heightFactor: .6,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: Offset(.4, -.04),
|
|
||||||
child: Image.asset('$assetPath/foreground-right.png', opacity: anim, fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user