| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:ui' as ui; |
| |
| import 'package:flutter/material.dart'; |
| |
| Future<ui.Image> loadImage(String asset) async { |
| final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromAsset(asset); |
| final ui.Codec codec = await PaintingBinding.instance.instantiateImageCodecWithSize(buffer); |
| final ui.FrameInfo frameInfo = await codec.getNextFrame(); |
| return frameInfo.image; |
| } |
| |
| class DrawVerticesPage extends StatefulWidget { |
| const DrawVerticesPage({super.key}); |
| |
| @override |
| State<DrawVerticesPage> createState() => _DrawVerticesPageState(); |
| } |
| |
| class _DrawVerticesPageState extends State<DrawVerticesPage> with SingleTickerProviderStateMixin { |
| late final AnimationController controller; |
| double tick = 0.0; |
| ui.Image? image; |
| |
| @override |
| void initState() { |
| super.initState(); |
| loadImage('packages/flutter_gallery_assets/food/butternut_squash_soup.png').then((ui.Image pending) { |
| setState(() { |
| image = pending; |
| }); |
| }); |
| controller = AnimationController(vsync: this, duration: const Duration(hours: 1)); |
| controller.addListener(() { |
| setState(() { |
| tick += 1; |
| }); |
| }); |
| controller.forward(from: 0); |
| } |
| |
| @override |
| void dispose() { |
| controller.dispose(); |
| super.dispose(); |
| } |
| |
| |
| @override |
| Widget build(BuildContext context) { |
| if (image == null) { |
| return const Placeholder(); |
| } |
| return CustomPaint( |
| size: const Size(500, 500), |
| painter: VerticesPainter(tick, image!), |
| child: Container(), |
| ); |
| } |
| } |
| |
| class VerticesPainter extends CustomPainter { |
| VerticesPainter(this.tick, this.image); |
| |
| final double tick; |
| final ui.Image image; |
| |
| @override |
| void paint(Canvas canvas, Size size) { |
| canvas.translate(0, tick); |
| final ui.Vertices vertices = ui.Vertices( |
| VertexMode.triangles, |
| const <Offset>[ |
| Offset.zero, |
| Offset(0, 250), |
| Offset(250, 0), |
| Offset(0, 250), |
| Offset(250, 0), |
| Offset(250, 250) |
| ], |
| textureCoordinates: <Offset>[ |
| Offset.zero, |
| Offset(0, image.height.toDouble()), |
| Offset(image.width.toDouble(), 0), |
| Offset(0, image.height.toDouble()), |
| Offset(image.width.toDouble(), 0), |
| Offset(image.width.toDouble(), image.height.toDouble()) |
| ], |
| colors: <Color>[ |
| Colors.red, |
| Colors.blue, |
| Colors.green, |
| Colors.red, |
| Colors.blue, |
| Colors.green, |
| ] |
| ); |
| canvas.drawVertices(vertices, BlendMode.plus, Paint()..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage)); |
| canvas.translate(250, 0); |
| canvas.drawVertices(vertices, BlendMode.plus, Paint()..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage)); |
| canvas.translate(0, 250); |
| canvas.drawVertices(vertices, BlendMode.plus, Paint()..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage)); |
| canvas.translate(-250, 0); |
| canvas.drawVertices(vertices, BlendMode.plus, Paint()..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage)); |
| } |
| |
| @override |
| bool shouldRepaint(covariant CustomPainter oldDelegate) { |
| return true; |
| } |
| } |