Javascript üzerinde canvas kullanarak pek çok yaratıcı işler yapılıyor. Flutter’da da benzer karmaşık animasyonları ve çizimleri yapabileceğimiz sınıf ve metotlarımız var.
Aynı isimli Canvas sınıfı Flutter’da da var fakat bunu direkt olarak kullanmayacağız bunun yerine CustomWidget widget’ını kullanacağız.
CustomPaint’in 5 parametresi var, aşağıda açıklamaya çalıştım.
const CustomPaint({ Key key, this.painter, // CustomPainter nesnesi this.foregroundPainter, // CustomPainter nesnesi, child widgetından sonra çizmeye başlar this.size = Size.zero, // child widget'ı yoksa boyut girebiliriz this.isComplex = false, // true ise sürekli çizim yapmaz, önbellek kullanır this.willChange = false, // tekrar çizim olması için true olmalı Widget child, // child widget }) : assert(size != null), assert(isComplex != null), assert(willChange != null), super(key: key, child: child);
Buradaki painter parametresi için kullanacağımız CustomPainter’a genişletilmiş bir sınıfımız olmalı.
class myCustomPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { // ana painter metodu, tüm çizim burada yapılır } @override bool shouldRepaint(myCustomPainter oldDelegate) => false; // önceki frame verisiyle kontrol ederek
Bir şeyler çizelim.
import 'package:flutter/material.dart'; class CustomPainterPractice extends StatelessWidget { @override Widget build(BuildContext context) { return Material( child: Padding( padding: const EdgeInsets.all(30.0), child: CustomPaint( painter: BobRoss(), ), ), ); } } class BobRoss extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint rectPaint = Paint(); rectPaint.style = PaintingStyle.fill; rectPaint.color = Colors.greenAccent; canvas.drawRect( Rect.fromLTWH(0.0, 0.0, size.width, 50), rectPaint ); } @override bool shouldRepaint(BobRoss oldDelegate) => false; }
Tam genişlikte ve 50 birim yükseklikte yeşil bir dikdörtgen çizdik. Material ve Padding widgetları ile sardığımız CustomWidget’a painter olarak oluşturduğumuz BobRoss widget’ını verdik. BobRoss widget’ımızın paint metodu bir canvas parametresi alıyor ve bu canvas nesnesine ait onlarca çizim metodu var.
Burada cascade notation denen bir çok faydalı bir syntax var. Kodumuzu daha derli toplu hale getirebiliriz bu yazım ile. Art arda iki nokta kullanılan bu yazımda aynı nesneye ait pek çok metodu ardışık olarak çağırabiliriz.
void paint(Canvas canvas, Size size) { canvas.drawRect( Rect.fromLTWH(0.0, 0.0, 50, 50), Paint() ..style = PaintingStyle.fill ..color = Colors.greenAccent, ); }
Şimdi canvası hareketlendirmeye geldi. shouldRepaint metodu true dönmeli öncelikle. Sonra gerekli verileri painter sınıfına ileterek çizime hareket katabiliriz. Verilerden kastım çizdiğiniz objenin koordinatları rengi vs. ya da zaman çizelgesinde hangi anın çizilmesini istediğiniz olabilir. Aşağıda tween ve curve kullanarak hareketli bir çizim oluşturmaya çalıştım.
import 'package:flutter/material.dart'; import 'package:flutter/animation.dart'; class CustomPainterPractice extends StatefulWidget { @override _CustomPainterPracticeState createState() => _CustomPainterPracticeState(); } class _CustomPainterPracticeState extends State<CustomPainterPractice> with SingleTickerProviderStateMixin{ Animation<double> animation; AnimationController controller; double drawTime = 0.0; double drawDuration = 2.0; @override void initState() { super.initState(); controller = AnimationController(vsync: this, duration: Duration(seconds: drawDuration.toInt())); animation = Tween<double>(begin: 0.001, end: drawDuration).animate(controller) ..addListener(() { setState(() { drawTime = animation.value; }); }); controller.forward(); } @override Widget build(BuildContext context) { return Material( child: Padding( padding: const EdgeInsets.all(30.0), child: CustomPaint( painter: BobRoss(drawTime, drawDuration), ), ), ); } @override void dispose() { controller.dispose(); super.dispose(); } } class BobRoss extends CustomPainter { final double drawTime; final double drawDuration; BobRoss(this.drawTime, this.drawDuration); @override void paint(Canvas canvas, Size size) { canvas.drawRect( Rect.fromLTWH(0.0, 0.0, size.width * (drawTime/drawDuration), 50), Paint() ..style = PaintingStyle.fill ..color = Colors.greenAccent, ); } @override bool shouldRepaint(BobRoss oldDelegate) => true; }
Önce StatefulWidget’a çevirdik widgetımızı çünkü bir state’imiz var artık. initState metodunda gerekli tanımlamaları yapıyoruz, bunları build metodunda yapamayız çinkü her setState çağrıldığında build metodu tekrar çalışacağından işler karışacaktır. İki saniyelik bir tween oluşturduk. drawTime / drawDuration değeri bize zaman çizelgesinde nerede olduğumuz verecek ve CustomPainter bu değer ile hesaplamasını yapıp çizimini yapacak.
Düz bir şekilde büyüyen animasyonumuz oldu. Curve ekleyerek animasyonu monotonluktan çıkarabiliriz. Aşağıdaki gif’in kodlarını şu gistte görebilirsiniz.
Medium hesabımdaki şu yazımın çevirisidir.
Bir cevap yazın