Hoạt ảnh thường làm tăng sức hấp dẫn trực quan của ứng dụng hoặc trang web và cải thiện mức độ tương tác tổng thể của người dùng. Theo một nghiên cứu của Forrester Research, các trang web có hoạt ảnh được thực hiện tốt sẽ tăng mức độ tương tác của người dùng lên tới 400%. Hoạt ảnh hấp dẫn có thể thu hút sự chú ý của người dùng và khuyến khích họ tương tác nhiều hơn với nền tảng. Tuy nhiên, có một đường cong học tập dành cho các nhà phát triển để thành thạo hoạt hình, đặc biệt là khi làm việc với các công cụ và kỹ thuật hoạt hình nâng cao hơn.
Nắm bắt Rive với tư cách là một nhà phát triển không có kinh nghiệm về hoạt ảnh có thể tương đối dễ dàng so với các công cụ hoặc khung hoạt ảnh khác. Rive (trước đây gọi là Flare) được thiết kế thân thiện với người dùng và dễ tiếp cận đối với các nhà phát triển, ngay cả những người có ít hoặc chưa có kinh nghiệm hoạt hình trước đó. Trong bài viết này, bạn sẽ tìm hiểu cách tạo hoạt ảnh Rive tuyệt đẹp đơn giản một cách dễ dàng và quản lý chúng trong ứng dụng Flutter của mình.
Giới thiệu về Rive🧙♂️
Hoạt hình đăng nhập tương tác đơn giản🚀
Kết luận🏋️♀️
Tài liệu tham khảo🧶
Rive là một công cụ hoạt hình và công cụ thời gian chạy mạnh mẽ và thân thiện với người dùng, cho phép các nhà phát triển và nhà thiết kế tạo ra các hoạt ảnh tương tác và tuyệt đẹp cho các nền tảng khác nhau, bao gồm ứng dụng dành cho thiết bị di động, ứng dụng web và trò chơi.
Dưới đây là các khái niệm chính:
Chúng tôi sẽ thực hiện quá trình tạo hoạt ảnh đăng nhập đơn giản và xuất nó sang ứng dụng Flutter của chúng tôi. Chúng tôi sẽ sử dụng StateMachine để quản lý tính tương tác của hoạt ảnh này trong ứng dụng. Cuối cùng, nó sẽ trông như thế này 👇🏽
Thực hiện theo các bước bên dưới để thiết lập phần tử trên bản vẽ Rive:
Tiếp theo, chúng tôi sẽ trói xương của chúng tôi và cân chúng. Ràng buộc đảm bảo rằng khi xương di chuyển, các phần tương ứng trên bề mặt của nhân vật cũng di chuyển theo, tạo ra ảo giác về sự biến dạng. Trọng số, còn được gọi là trọng số đỉnh, liên quan đến việc gán các giá trị ảnh hưởng (trọng số) cho từng đỉnh của lưới của ký tự dựa trên mức độ gần của nó với các xương cụ thể. Chúng tôi sẽ điều hướng đến đường dẫn của hình dạng mà chúng tôi sẽ ràng buộc. Đối với cổ, đây là cách chúng tôi buộc nó vào xương cổ.
Sau khi liên kết các xương, chúng tôi đặt các đỉnh bằng cách gán trọng số cho chúng. Ở đây, lưu ý rằng chúng tôi đã đặt tập hợp đỉnh cuối cùng lên 50% vì chúng tôi muốn hai xương có tác dụng 50% đối với chúng. Bạn nên sử dụng 50%, đặc biệt khi các đỉnh được đặt bao phủ một phần ảnh hưởng đến hai xương. Bây giờ, chúng ta sẽ làm tương tự với đường dẫn tóc. Chúng tôi cũng sẽ thay đổi xương bên trái và bên phải từ một thành hai xương để giúp chúng tôi đạt được chuyển động bồng bềnh mà chúng tôi muốn cho tóc.
Chúng tôi muốn có hiệu ứng nhấp nháy trong hoạt ảnh này, để đạt được điều này, chúng tôi sẽ sử dụng tính năng clip trên hai hình con mắt như thế này 👇🏽
Tiếp theo, chúng tôi sẽ thêm theo dõi đầu bằng cách sử dụng các ràng buộc dịch cho phần tử này vì chúng tôi muốn di chuyển đầu trong hoạt ảnh. Vì nó là phần tử 2d, nên việc thêm các ràng buộc dịch thuật sẽ tạo cho nó chiều sâu và một số dạng hiệu ứng 3d. Chọn mọi thứ và nhóm nó. Bây giờ chúng tôi có một nhóm duy nhất.
Sau đó, ở góc trên cùng bên trái, chọn công cụ nhóm và tạo một nhóm ở giữa đầu (tại khu vực mũi). Trên thanh công cụ bên phải, thay đổi kiểu của nó từ nhóm thành mục tiêu, đặt tên là ctrl_front, sao chép nó và đặt tên trùng lặp là ctrl_back.
Đối với ctrl_back đích, hãy chọn tùy chọn ràng buộc từ thanh công cụ bên phải. Chọn các ràng buộc dịch thuật từ danh sách các tùy chọn ràng buộc có sẵn. Nhấp vào biểu tượng trước tùy chọn ràng buộc đã chọn để đặt thuộc tính của nó.
Đặt cường độ thành -100 và đặt mục tiêu của nó thành ctrl phía trước. Bây giờ khi bạn di chuyển ctrl phía trước, ctrl phía sau sẽ di chuyển theo hướng ngược lại. Nó sẽ giúp chúng ta đặt giới hạn cho các phần của khuôn mặt sẽ di chuyển theo hướng ngược lại, chẳng hạn như tai. Nó sẽ trông như thế này 👇🏽
Bây giờ chúng ta sẽ thiết lập các ràng buộc cho phần còn lại của khuôn mặt. Chúng tôi cũng sẽ nhóm mắt (trái và phải) và tai (trái và phải) để giúp chúng tôi quản lý chúng tốt hơn. Chúng ta sẽ đặt ràng buộc cho mắt như thế này 👇🏽
Nhóm | sức mạnh hạn chế | vị trí gốc | Mục tiêu |
---|---|---|---|
kính | 5% | giống như nguồn gốc ctrl_front | ctrl_front |
lông mày | 10% | giống như nguồn gốc ctrl_front | ctrl_front |
đôi tai | 5% | không cần đặt gốc | ctrl_back |
mũi | 5% | giống như nguồn gốc ctrl_front | ctrl_front |
khuôn mặt | 5% | giống như nguồn gốc ctrl_front | ctrl_front |
Chúng ta không cần đặt ra những ràng buộc cho đôi môi.
Đây là giao diện sau khi chúng tôi hoàn thành việc thêm tất cả các ràng buộc của mình 👇🏽
💃🏽 🥳 Xin chúc mừng, chúng tôi đã chuẩn bị thành công yếu tố sẵn sàng cho loại hoạt hình mà chúng tôi muốn đạt được. Chà!!
Trên thanh công cụ bên phải, nhấn vào nút Animate để chuyển sang giao diện tạo ảnh động. Chúng tôi sẽ tạo sáu dòng thời gian hoạt hình và kết hợp mọi thứ với một máy trạng thái. Trong dòng thời gian, bằng cách sử dụng những gì chúng tôi đã thiết lập trước đó với xương và ràng buộc, chúng tôi có thể đặt các khung hình chính để tạo hoạt ảnh mà chúng tôi muốn đạt được.
Hoạt hình dòng thời gian đầu tiên là hoạt hình nhàn rỗi. Nó sẽ là trạng thái Idle của hoạt hình. Chúng tôi sẽ sử dụng điều này khi phần tử hoạt hình không được sử dụng.
Đối với hoạt hình nhàn rỗi này, chúng ta sẽ tạo ra ảo ảnh về hơi thở, chuyển động nhẹ của tóc và chớp mắt. Sử dụng các phần tử xương cổ, xương tóc và mắt phải/trái, chúng ta sẽ đặt các khung hình chính cần thiết ở các tư thế khác nhau, nghĩa là chúng ta có thể đặt các thuộc tính cụ thể của mục đã chọn trên các điểm trên dòng thời gian. Xem xét kiểu chuyển đổi từ khung hình chính này sang khung hình chính tiếp theo, chúng tôi sẽ chọn loại nội suy mà chúng tôi cần. Bạn có thể tìm thấy nó ở dưới cùng bên phải của phần Dòng thời gian. Nội suy là giữ, tuyến tính hoặc đường cong, tùy thuộc vào cách bạn muốn di chuyển từ khung hình chính này sang khung hình chính tiếp theo. Nó sẽ trông như thế này 👇🏽
Từ gif ở trên, bạn có thể nhận thấy rằng trên các khung hình chính khác nhau trên dòng thời gian, chúng tôi đã đặt các tư thế khác nhau cho các mục đã chọn. Quá trình chuyển đổi này từ khung hình chính này sang khung hình chính khác tạo thành hoạt ảnh. Sử dụng quy trình tương tự này, chúng tôi sẽ tạo năm mốc thời gian khác. Bạn có thể nhấp vào đây để xem hoạt ảnh này và xem chi tiết các mốc thời gian khác nhau. Nó trông như thế này 👇🏽
Chúng ta đã đi đến phần cuối cùng của quá trình hoạt hình này. Máy trạng thái là một cách trực quan để kết nối hoạt ảnh. Sử dụng máy trạng thái, chúng tôi có thể kiểm soát hoạt ảnh nào sẽ phát dựa trên đầu vào mà chúng tôi đã đặt. Chúng tôi có thể trộn hoặc kết hợp hai hoặc nhiều hoạt ảnh dòng thời gian để chúng phát đồng thời. Chúng ta phải chọn đúng loại đầu vào trong máy trạng thái vì đây là thứ chúng ta sẽ sử dụng để điều khiển hoạt ảnh trong ứng dụng.
Trong máy trạng thái, chúng ta có ba loại đầu vào:
Trên bảng Hoạt hình, nhấp vào nút dấu cộng và tạo Máy trạng thái. Chúng tôi sẽ đặt tên nó là Login State Machine . Tên này rất quan trọng vì đó là những gì chúng ta sẽ cần để xác định máy trạng thái của mình sau này trong mã.
Thực hiện theo các bước bên dưới để thiết lập máy trạng thái của bạn:
Bây giờ hoạt hình hoàn chỉnh trong máy trạng thái sẽ trông như thế này 👇🏽
Kiểm tra hoạt hình đầy đủ và máy trạng thái ở đây .
Xin chúc mừng 🥳, chúng ta đã tạo hoạt ảnh thành công cho phần tử của mình và thiết lập phần tử đó với một máy trạng thái! Tuy nhiên trước khi xuất file rive chúng ta sẽ thay đổi màu nền và màu áo của nhân vật. Nó sẽ trông như thế này👇🏽
Màu nền là (#B581EB) và màu áo của nhân vật là (#BD08D7)
Đây là liên kết đến hình ảnh động để xem mọi thứ chi tiết
Chúng tôi sẽ sử dụng hình ảnh động này trên trang Đăng nhập của chúng tôi. Tạo dự án ứng dụng Flutter và thêm phần phụ thuộc Rive vào pubspec.yaml
dependencies: rive: ^0.11.12
Ngoài ra, hãy thêm tệp Rive đã xuất vào tài sản dự án của bạn. Bây giờ chúng ta có thể tiếp tục tạo giao diện người dùng dựa trên thiết kế của mình. Chúng tôi mong muốn có hoạt ảnh như sau:
Đầu tiên chúng ta sẽ định nghĩa một số thứ trước chức năng Widget Build.
///Login details String emailCred = "[email protected]"; String passwordCred = "123456"; /// input form controller FocusNode emailFocusNode = FocusNode(); TextEditingController emailCtr = TextEditingController(); FocusNode passwordFocusNode = FocusNode(); TextEditingController passwordCtr = TextEditingController(); /// rive controller and input values StateMachineController? controller; SMIInput<bool>? check; SMIInput<double>? look; SMIInput<bool>? success; SMIInput<bool>? fail; bool isLoading = false; bool isError = false; @override void initState() { emailFocusNode.addListener(emailFocus); passwordFocusNode.addListener(passwordFocus); super.initState(); } @override void dispose() { emailFocusNode.removeListener(emailFocus); passwordFocusNode.removeListener(passwordFocus); super.dispose(); } void emailFocus() { check?.change(emailFocusNode.hasFocus); } void passwordFocus() { check?.change(passwordFocusNode.hasFocus); }
Ở đây, chúng ta có thể lưu ý những điều sau:
emailFocus
và passwordFocus
, đầu vào kiểm tra được thay đổi dựa trên boolean FocusNode.hasFocus
initState
và dispose
, chúng ta thấy các Trình nghe được thêm và xóa. Thính giả quen nghe để tập trung thay đổi.
Bạn có thể kiểm tra mã cho giao diện người dùng và phần còn lại của mã tại đây . Đoạn mã này cho biết cách thêm RiveAsset:
SizedBox( height: 250, width: 250, child: RiveAnimation.asset( "assets/login_screen.riv", fit: BoxFit.fitHeight, stateMachines: const ["Login State Machine"], onInit: (artboard) { controller = StateMachineController.fromArtboard( artboard, "Login State Machine", ); if (controller == null) return; artboard.addController(controller!); check = controller?.findInput("check"); look = controller?.findInput("look"); success = controller?.findInput("success"); fail = controller?.findInput("fail"); }, ), ),
Từ đoạn mã trên, chúng ta có thể lưu ý những điều sau:
Đây là mã cho chức năng đăng nhập:
void login()async{ //extract the text coming from the text fields final email = emailCtr.text; final password = passwordCtr.text; //Set loading boolean to true and delay to give an illusion of loading setState(() { isLoading = true; }); await Future.delayed( const Duration(milliseconds: 2000), ); // check if details entered is the same as the correct creditials defined if (email == emailCred && password == passwordCred) { //if correct trigger the success input and set error boolean to false success?.change(true); setState(() { isError = false; }); if(context.mounted){ // delay and navigate to home screen await Future.delayed( const Duration(seconds: 2),(){ Navigator.push(context, MaterialPageRoute(builder: (context) =>const HomeScreen())); }); } } else { // if details don't match defined credentials // set error boolean to true and trigger the fail input // set loading boolean to false setState(() { isError = true; }); fail?.change(true); } setState(() { isLoading = false; }); }
Kiểm tra mã hoàn chỉnh ở đây .
Bằng cách này, chúng tôi đã hoàn thành mã hoạt hình Đăng nhập của mình. Đây là cách mọi thứ trông:
Chúc mừng! Chúng tôi đã hoàn thành hoạt ảnh đăng nhập tương tác đơn giản này. Dưới đây là tổng quan về mọi thứ chúng tôi có thể thực hiện:
Làm theo từng bước hướng dẫn này, bạn có thể gặp phải một số khó khăn, nhưng sẽ dễ dàng hơn khi thực hành. Bạn có thể liên hệ với tôi trên Twitter hoặc nhận xét nếu bạn cần trợ giúp trong khi làm theo hướng dẫn này.
Hãy xem các video hướng dẫn này để hiểu rõ hơn về hoạt hình Rive
Bạn cũng có thể xem kênh Rive để biết một số video hướng dẫn về hoạt ảnh Rive.
Cũng được xuất bản ở đây .