Bir önceki yazıda Tween ile bir değeri değiştirerek bunu widget içinde kullanıp bir animasyon oluşturmaya çalışmıştık. Şimdi diğer bir animasyon türü olan fizik bazlı animasyonları tanıyalım.
Gerçek dünya hareketlerini taklit etmeye yaran animasyon sınıfları bu gruba dahil ediliyor. Yer çekimi ya da bir yayın salınımı algısını vermeye çalıştığınızda bunların uğraştırıcı matematik hesaplarını kodumuza ekleyip karıştırmadan sade bir simülasyon elde edebiliriz.
Şurada bütün simülasyon sınıflarını görebilirsiniz. Bunlardan GravitySimulation ve SpringSimulation sınıfları ile birer örnek yapalım.
import 'package:flutter/material.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/physics.dart'; void main() => runApp(PhysicsAnimation()); class PhysicsAnimation extends StatefulWidget { _PhysicsAnimation createState() => _PhysicsAnimation(); } class _PhysicsAnimation extends State<PhysicsAnimation> with SingleTickerProviderStateMixin{ AnimationController controller; GravitySimulation simulation; @override void initState() { super.initState(); simulation = GravitySimulation( 100.0, // ivme 0.0, // başlangıç 500.0, // bitiş 0.0, // başlangıç hızı ); controller = AnimationController(vsync: this, upperBound: 500) ..addListener(() { setState(() {}); }); controller.animateWith(simulation); } @override Widget build(BuildContext context) { return MaterialApp( home: Stack( children: [ Positioned( left: 50, top: controller.value, height: 10, //animation.value, width: 10, //animation.value, child: Container( color: Colors.redAccent, ), ), ] ), ); } @override void dispose() { controller.dispose(); super.dispose(); } }
Bazı açıklamaları Tween animasyon yazısında zaten yapmıştım. Bu bölüme özel kısımlardan bahsedeyim.
GravitySimulation: Yer çekimi simülasyon için oluşturulmuş bir sınıf. İvme başlangıç ve bitiş pozisyonları ve başlangıç hızı için değerler verebiliyoruz. Bu örnekte 500 piksellik hedefe 100 piksellik ivme ile gitmesini istedik.
upperBound: Belki bir bug olabilir fakat simülasyon kullanıldığında verdiğimiz 500 değeri bir işe yaramayacak çünkü AnimationController sınıfında bir üst değer limiti var. Ve bu limit ön tanımlı olarak 1. Yani simülasyon kullandığınızda değeriniz bire gelip takılıyorsa bu değeri tanımlamanız gerekli. Bir de lowerBound var ön tanımlı olarak sıfır ama bu örnekte önemli değil. Başlangıç pozisyonunu negatif vererek ekran dışından gelmesini isteseydik elemanımızın o zaman lowerBound için bir değer vermemiz gerekecekti.
controller.animateWith: Burada animasyon kontrolcüsü değerimize tanımladığımız simülasyonu aktararak bununla ilerle diyoruz. Farkettiyseniz tween örneklerinde olduğu gibi bir zaman değişkeni yok çünkü zaman simulation içinde tanımladığımız değerlerden hesaplanarak oluşacak.
Animasyonu hazırladıktan sonra Stack widget’ı içinde bir Positioned oluşturarak top değerine controller.value veriyoruz. Aşağıdaki animasyonu elde ediyoruz.
Şimdi yay simülasyonu sınıfından bir örnek yapalım.
import 'package:flutter/material.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/physics.dart'; void main() => runApp(PhysicsAnimation()); class PhysicsAnimation extends StatefulWidget { _PhysicsAnimation createState() => _PhysicsAnimation(); } class _PhysicsAnimation extends State<PhysicsAnimation> with SingleTickerProviderStateMixin{ AnimationController controller; SpringSimulation simulation; Animation<double> animation; @override void initState() { super.initState(); simulation = SpringSimulation( SpringDescription( mass: 1, // kütle stiffness: 100, // yay sertliği damping: 1, // zayıflama ), 0.0, // başlangıç 300.0, // bitiş 10, // hız ); controller = AnimationController(vsync: this, upperBound: 500, ) ..addListener(() { print(controller.value); setState(() {}); }); controller.animateWith(simulation); } @override Widget build(BuildContext context) { return MaterialApp( home: Stack( children: [ Positioned( left: 50, top: controller.value, height: 10, width: 10, child: Container( color: Colors.redAccent, ), ), ] ), ); } @override void dispose() { controller.dispose(); super.dispose(); } }
Önceki örnek ile aynı. Sadece simulation için başka bir sınıf tanımladık ve değerlerini girdik. upperBound için yayın hareket alanı bitiş noktasının ötesinde olacağı için daha yüksek bir değer girmekte fayda var.
SpringSimulation için girilen parametrelerin yanlarına yazdım açıklamaları. Bunları anlamlandırmanın en uygun yolu örnek üzerinde olur.
mass: 1 ve stiffness: 100 vererek damping değerini değiştirdiğimizde neler olduğunu aşağıdaki görselden görebilirsiniz. Damping arttıkça salınım sayısı azalıyor.
Bu sefer stiffness değerini değiştirelim. (mass:1 ve damping:1) Stiffness değeri de salınımın gücünü arttırıyor gibi. Ama tüm salınımlar aynı zamanda sona yaklaşıyorlar.
Malum gif masraflı bir şey bu yüzden kısa tuttum ve salınımların tamamen bitmesini beklemedim.
Medium hesabımdaki şu yazımın çevirisidir.
Bir cevap yazın