Updated images
BIN
assets/images/pyramids/1.5x/foreground-back.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/images/pyramids/1.5x/foreground-front.png
Normal file
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 26 KiB |
BIN
assets/images/pyramids/4.0x/foreground-back.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
assets/images/pyramids/4.0x/foreground-front.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 6.8 KiB |
145
lib/ui/wonder_illustrations/common/illustration_fg.dart
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,9 @@ import 'package:wonders/common_libs.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_config.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 {
|
class IllustrationMg extends StatelessWidget {
|
||||||
const IllustrationMg(
|
const IllustrationMg(
|
||||||
this.imagePath, {
|
this.imagePath, {
|
||||||
|
@ -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_fg.dart';
|
||||||
import 'package:wonders/ui/wonder_illustrations/common/illustration_mg.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_hero.dart';
|
||||||
@ -78,6 +79,20 @@ class PyramidsGizaIllustration 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);
|
final curvedAnim = Curves.easeOut.transform(anim.value);
|
||||||
return [
|
return [
|
||||||
|
IllustrationPiece(
|
||||||
|
type: WonderType.pyramidsGiza,
|
||||||
|
anim: anim,
|
||||||
|
fileName: 'foreground-back.png',
|
||||||
|
heightFactor: .5,
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
IllustrationPiece(
|
||||||
|
type: WonderType.pyramidsGiza,
|
||||||
|
anim: anim,
|
||||||
|
fileName: 'foreground-front.png',
|
||||||
|
heightFactor: .5,
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
)
|
||||||
// Transform.scale(
|
// Transform.scale(
|
||||||
// scale: 1 + config.zoom * .2,
|
// scale: 1 + config.zoom * .2,
|
||||||
// child: Transform.translate(
|
// child: Transform.translate(
|
||||||
|