Search code examples
flutterimageanimationflutter-animation

How to show Image part by part above a text in Flutter?


I want to make somthing like this in flutter a blue iamge above a text but it's displied part by part ,how I can made somthing like this or if there is any good libery for that I on ready google it but I didnt find what excatly what I want

I try this but it's not what I want excatly

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "App",
      home: Test(),
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
  double rightValue = 1000;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: SafeArea(
          child: Center(
            child: Stack(
              alignment: Alignment.center,
              children: [
                AnimatedPositioned(
                  duration: Duration(seconds: 2),
                  right: rightValue,
                  child: Image.asset('assets/images/bg.png'),
                ),
                Center(
                  child: Text('Hello world',
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 24,
                          fontWeight: FontWeight.bold)),
                ),
                //),
              ],
            ),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              rightValue = 0;
            });
          },
        ),
      ),
    );
  }
}

Solution

  • the idea is using CustomClipper, animate it to reveal image :

    EDIT -- as of yeasin suggestion, you can animate the text with color tween, warp it in stack.

    here edited result :

    enter image description here

    code :

    class Testing extends StatefulWidget {
      const Testing({Key? key}) : super(key: key);
    
      @override
      State<Testing> createState() => _TestingState();
    }
    
    class _TestingState extends State<Testing> with SingleTickerProviderStateMixin {
      late final AnimationController _animationController;
      late final Animation<double> _animation;
      late final Animation<Color?> _animationColor;
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        _animationController = AnimationController(
            vsync: this, duration: const Duration(milliseconds: 1200))
          ..repeat(reverse: false);
        _animation = Tween<double>(begin: 0.0, end: 1.0).animate(
            CurvedAnimation(parent: _animationController, curve: Curves.ease));
        _animationColor = ColorTween(begin: Colors.black, end: Colors.white)
            .animate(
                CurvedAnimation(parent: _animationController, curve: Curves.ease));
      }
    
      @override
      void dispose() {
        _animationController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Stack(
            children: [
              Center(
                child: AnimatedBuilder(
                  animation: _animationController,
                  builder: (context, child) {
                    return ClipPath(
                      clipper: MyClipper(anim: _animation.value),
                      child: Container(
                        height: 300.0,
                        width: 300.0,
                        color: Colors.blue,
                      ),
                    );
                  },
                ),
              ),
              AnimatedBuilder(
                animation: _animationController,
                builder: (context, _) {
                  return Center(
                      child: Text(
                    "your image",
                    style: TextStyle(
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold,
                        color: _animationColor.value),
                  ));
                },
              ),
            ],
          ),
        );
      }
    }
    
    class MyClipper extends CustomClipper<Path> {
      final double anim;
      MyClipper({required this.anim});
      @override
      getClip(Size size) {
        // TODO: implement getClip
        var rect = Rect.fromLTWH(0.0, 0.0, size.width * anim, size.height);
        var path = Path();
        path.addRect(rect);
        return path;
      }
    
      @override
      bool shouldReclip(covariant MyClipper oldClipper) {
        return oldClipper != this;
      }
    }