Skip to content

Commit f7eac2d

Browse files
committed
Images and two side support added!
1 parent e49ecf1 commit f7eac2d

File tree

8 files changed

+189
-18
lines changed

8 files changed

+189
-18
lines changed

assets/images/vinyl/cover_1.png

687 KB
Loading

assets/images/vinyl/cover_2.png

83.2 KB
Loading

assets/images/vinyl/cover_3.png

545 KB
Loading

assets/images/vinyl/vinyl.png

200 KB
Loading

assets/images/vinyl/vinyl_half.png

104 KB
Loading

lib/vinyl/exmaples/glass_card.dart

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import 'package:flutter/material.dart';
2+
import 'dart:ui';
3+
4+
class GlassCardPage extends StatelessWidget {
5+
const GlassCardPage({Key? key}) : super(key: key);
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
return Scaffold(
10+
appBar: AppBar(
11+
title: const Text('Glass Card'),
12+
),
13+
body: ListView.builder(
14+
itemCount: 10,
15+
itemBuilder: (BuildContext context, int index) {
16+
return GlassCard(
17+
imageUrl:
18+
'https://i.ytimg.com/vi/jfcbqU4Ct74/maxresdefault.jpg', // Replace with your image URL
19+
);
20+
},
21+
),
22+
);
23+
}
24+
}
25+
26+
class GlassCard extends StatelessWidget {
27+
final String imageUrl;
28+
29+
const GlassCard({Key? key, required this.imageUrl}) : super(key: key);
30+
31+
@override
32+
Widget build(BuildContext context) {
33+
return Card(
34+
clipBehavior: Clip.antiAlias,
35+
shape: RoundedRectangleBorder(
36+
borderRadius: BorderRadius.circular(15.0),
37+
),
38+
child: Stack(
39+
children: [
40+
// Base image
41+
Image.network(
42+
imageUrl,
43+
fit: BoxFit.cover,
44+
height: 200,
45+
width: double.infinity,
46+
),
47+
// Glass effect overlay
48+
Positioned.fill(
49+
child: ClipRRect(
50+
borderRadius: BorderRadius.circular(15.0),
51+
child: BackdropFilter(
52+
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
53+
child: Container(
54+
color: Colors.white.withOpacity(0.2),
55+
child: Container(
56+
decoration: BoxDecoration(
57+
border: Border.all(
58+
color: Colors.white.withOpacity(0.2),
59+
width: 1.5,
60+
),
61+
borderRadius: BorderRadius.circular(15.0),
62+
gradient: LinearGradient(
63+
begin: Alignment.topLeft,
64+
end: Alignment.bottomRight,
65+
colors: [
66+
Colors.white.withOpacity(0.5),
67+
Colors.white.withOpacity(0.1),
68+
],
69+
),
70+
),
71+
),
72+
),
73+
),
74+
),
75+
),
76+
// Content
77+
Padding(
78+
padding: const EdgeInsets.all(16.0),
79+
child: Text(
80+
'Glass Card',
81+
style: TextStyle(
82+
color: Colors.white,
83+
fontSize: 24,
84+
fontWeight: FontWeight.bold,
85+
),
86+
),
87+
),
88+
],
89+
),
90+
);
91+
}
92+
}

lib/vinyl/vinyl.dart

+92-18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart';
88
import 'package:fx_2_folder/vinyl/camera_simulation.dart';
99
import 'package:fx_2_folder/vinyl/card_stack_4_angles.dart';
1010
import 'package:fx_2_folder/vinyl/easing/super_duper_ease_in.dart';
11+
import 'package:fx_2_folder/vinyl/exmaples/glass_card.dart';
1112
import 'package:fx_2_folder/vinyl/exmaples/spring_examples.dart';
1213
import 'package:fx_2_folder/vinyl/exmaples/spring_playground.dart';
1314
import 'package:fx_2_folder/vinyl/transform_examples.dart';
@@ -26,7 +27,10 @@ class VinylHomeWidget extends StatelessWidget {
2627
// body: TransformDemo(),
2728

2829
// body: SpringAnimationsPage(),
30+
2931
body: TransformApp(),
32+
// body: GlassCardPage(),
33+
3034
// body: SpringAnimationsDemo(),
3135
);
3236
}
@@ -50,6 +54,9 @@ class _TransformAppState extends State<TransformApp>
5054
late AnimationController animParentController;
5155
late Animation<double> _headBowForwardAnimation;
5256

57+
late AnimationController vinylController;
58+
late Animation<double> _vinylJumpAnimation;
59+
5360
final List<VinylItem> _vinylItems = List.from(vinylItems);
5461

5562
String firstVinylId = vinylItems[0].id;
@@ -102,7 +109,7 @@ class _TransformAppState extends State<TransformApp>
102109
..rotateY(323 * pi / 180) // horixontal
103110
..rotateX(baseRotationX +
104111
sin(_headBowForwardAnimation.value * pi) *
105-
5 *
112+
10 *
106113
pi /
107114
180 +
108115
_rotateX) // vertical
@@ -163,12 +170,15 @@ class _TransformAppState extends State<TransformApp>
163170
_combinedVerticalAnimation,
164171
_topJumpAnimation,
165172
_topMoveForwardAnimation,
173+
_vinylJumpAnimation,
166174
]),
167175
builder: (context, child) {
168176
return Stack(
169177
children: List.generate(_vinylItems.length, (index) {
170178
var vinylItem = _vinylItems[index];
171179
// if (vinylItem.id == 'vinyl_3') {
180+
bool isSecond =
181+
false; // At this moment, the second card is the first one in the stack
172182
if (vinylItem.id == vinylOrder[0]) {
173183
vinylItem.verticalAnimationValue =
174184
_combinedVerticalAnimation.value;
@@ -177,6 +187,7 @@ class _TransformAppState extends State<TransformApp>
177187
vinylItem.rotateX = _flipAnimation.value;
178188
// } else if (_vinylItems[index].id == 'vinyl_2') {
179189
} else if (_vinylItems[index].id == vinylOrder[1]) {
190+
isSecond = true;
180191
vinylItem.verticalAnimationValue = _topJumpAnimation.value;
181192
vinylItem.zPositionValue = -50.0 + _topMoveForwardAnimation.value;
182193
vinylItem.rotateX = 0.0;
@@ -190,20 +201,57 @@ class _TransformAppState extends State<TransformApp>
190201

191202
return Transform(
192203
transform: Matrix4.identity()
204+
..setEntry(3, 2, 0.001)
193205
..translate(0.0, vinylItem.verticalAnimationValue,
194206
vinylItem.zPositionValue)
195207
..rotateX(vinylItem.rotateX),
196208
alignment: Alignment.center, // -index * 50.0
197-
child: Container(
198-
width: 200,
199-
height: 200,
200-
color: _vinylItems[index].color,
201-
child: Center(
202-
child: Text(
203-
'Layer ${index + 1} + id ${_vinylItems[index].id}',
204-
style: TextStyle(color: Colors.white),
209+
child: Stack(
210+
children: [
211+
// Container(
212+
// width: 200,
213+
// height: 200,
214+
// color: _vinylItems[index].color,
215+
// child: Text(
216+
// 'Layer ${index + 1} + id ${_vinylItems[index].id}',
217+
// style: TextStyle(color: Colors.white),
218+
// ),
219+
// ),
220+
Container(
221+
width: 200,
222+
height: 200,
223+
child: Image.asset(
224+
vinylItem.asset,
225+
fit: BoxFit.fill,
226+
),
205227
),
206-
),
228+
Transform.translate(
229+
offset: Offset(
230+
0,
231+
isSecond
232+
? _vinylJumpAnimation.value
233+
: 0), // Move up and down
234+
child: Container(
235+
width: 200,
236+
height: 200,
237+
// color: _vinylItems[index].color,
238+
child: Image.asset(
239+
"assets/images/vinyl/vinyl.png",
240+
fit: BoxFit.fill,
241+
),
242+
),
243+
),
244+
245+
if (isFrontImage(vinylItem.rotateX))
246+
Container(
247+
width: 200,
248+
height: 200,
249+
child: Image.asset(
250+
vinylItem.asset,
251+
fit: BoxFit.fill,
252+
),
253+
),
254+
],
207255
),
208256
);
209257
}),
@@ -212,6 +260,12 @@ class _TransformAppState extends State<TransformApp>
212260
);
213261
}
214262

263+
bool isFrontImage(double angle) {
264+
const degrees90 = pi / 2;
265+
const degrees270 = 3 * pi / 2;
266+
return angle <= degrees90 || angle >= degrees270;
267+
}
268+
215269
void resetAnimation() {
216270
animController.dispose();
217271
animParentController.dispose();
@@ -228,10 +282,13 @@ class _TransformAppState extends State<TransformApp>
228282

229283
initAnimations() {
230284
animController = AnimationController(
231-
vsync: this, duration: const Duration(milliseconds: 1000))
285+
vsync: this, duration: const Duration(milliseconds: 1200))
232286
..addListener(_animationHooks);
233287

234288
animParentController = AnimationController(
289+
vsync: this, duration: const Duration(milliseconds: 600));
290+
291+
vinylController = AnimationController(
235292
vsync: this, duration: const Duration(milliseconds: 300));
236293

237294
// Add a status listener
@@ -249,23 +306,25 @@ class _TransformAppState extends State<TransformApp>
249306
animController.forward();
250307
}
251308
});
309+
// Start the animation and reverse it
310+
// _controller.forward().then((_) => _controller.reverse());
252311

253312
// Combine vertical animations on the first Vinyl!
254313
_combinedVerticalAnimation = TweenSequence<double>([
255314
TweenSequenceItem(
256315
tween: Tween<double>(begin: 0.0, end: 150.0)
257316
.chain(CurveTween(curve: Curves.linear)),
258-
weight: 25.0,
317+
weight: 30.0,
259318
),
260319
TweenSequenceItem(
261320
tween: Tween<double>(begin: 150.0, end: 150.0)
262321
.chain(CurveTween(curve: Curves.linear)),
263-
weight: 50.0,
322+
weight: 40.0,
264323
),
265324
TweenSequenceItem(
266325
tween: Tween<double>(begin: 150.0, end: 0.0)
267326
.chain(CurveTween(curve: Curves.linear)),
268-
weight: 25.0,
327+
weight: 30.0,
269328
),
270329
]).animate(animController);
271330

@@ -276,17 +335,17 @@ class _TransformAppState extends State<TransformApp>
276335
TweenSequenceItem(
277336
tween: Tween<double>(begin: 0.0, end: pi / 2)
278337
.chain(CurveTween(curve: Curves.linear)),
279-
weight: 25.0,
338+
weight: 30.0,
280339
),
281340
TweenSequenceItem(
282341
tween: Tween<double>(begin: pi / 2, end: 3 * pi / 2)
283342
.chain(CurveTween(curve: Curves.linear)),
284-
weight: 50.0,
343+
weight: 40.0,
285344
),
286345
TweenSequenceItem(
287346
tween: Tween<double>(begin: 3 * pi / 2, end: 2 * pi)
288347
.chain(CurveTween(curve: Curves.linear)),
289-
weight: 25.0,
348+
weight: 30.0,
290349
),
291350
]).animate(animController);
292351

@@ -327,9 +386,17 @@ class _TransformAppState extends State<TransformApp>
327386
_headBowForwardAnimation = Tween<double>(begin: 0, end: 1).animate(
328387
CurvedAnimation(
329388
parent: animParentController,
330-
curve: SnappySpringCurve() //BouncyElasticCurve()
389+
curve: Interval(0.0, 0.75,
390+
curve: SnappySpringCurve()) //BouncyElasticCurve()
331391
),
332392
);
393+
394+
_vinylJumpAnimation = Tween<double>(begin: 0, end: -50).animate(
395+
CurvedAnimation(
396+
parent: vinylController,
397+
curve: Interval(0.0, 1.0, curve: SnappySpringCurve()),
398+
),
399+
);
333400
}
334401

335402
Widget _buildSlider({
@@ -359,6 +426,8 @@ class _TransformAppState extends State<TransformApp>
359426
_isStackReordered = true;
360427
} else if (animController.value < 0.5) {
361428
_isStackReordered = false;
429+
} else if (animController.value > 0.74) {
430+
vinylController.forward().then((_) => vinylController.reverse());
362431
}
363432
}
364433

@@ -384,13 +453,15 @@ class _TransformAppState extends State<TransformApp>
384453
class VinylItem {
385454
final String id;
386455
final Color color;
456+
final String asset;
387457
double verticalAnimationValue = 0.0;
388458
double zPositionValue = 0.0;
389459
double rotateX = 0.0;
390460

391461
VinylItem(
392462
{required this.id,
393463
required this.color,
464+
required this.asset,
394465
this.verticalAnimationValue = 0.0,
395466
this.zPositionValue = 0.0,
396467
this.rotateX = 0.0});
@@ -405,18 +476,21 @@ final List<VinylItem> vinylItems = [
405476
VinylItem(
406477
id: 'vinyl_1',
407478
color: Colors.green,
479+
asset: "assets/images/vinyl/cover_1.png",
408480
verticalAnimationValue: 0.0,
409481
zPositionValue: 0.0,
410482
rotateX: 0.0),
411483
VinylItem(
412484
id: 'vinyl_2',
413485
color: Colors.yellow,
486+
asset: "assets/images/vinyl/cover_2.png",
414487
verticalAnimationValue: 0.0,
415488
zPositionValue: 0.0,
416489
rotateX: 0.0),
417490
VinylItem(
418491
id: 'vinyl_3',
419492
color: Colors.purple,
493+
asset: "assets/images/vinyl/cover_3.png",
420494
verticalAnimationValue: 0.0,
421495
zPositionValue: 0.0,
422496
rotateX: 0.0),

pubspec.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ flutter:
7575
- assets/images/4_bird.png
7676
- assets/images/4_bird_spine.png
7777
- assets/images/tracing_cards.png
78+
- assets/images/vinyl/cover_1.png
79+
- assets/images/vinyl/cover_2.png
80+
- assets/images/vinyl/cover_3.png
81+
- assets/images/vinyl/vinyl.png
82+
7883

7984
# An image asset can refer to one or more resolution-specific "variants", see
8085
# https://flutter.dev/assets-and-images/#resolution-aware

0 commit comments

Comments
 (0)