'How to animate images on mouse hover using Flutter for Web?
I am a JavaScript developer and I am new to Flutter. I just want to animate a set of images on mouse hover like this using Flutter for Web. It includes Scaling, Opacity and Grayscale transformations. How to accomplish this in Flutter? Thanks in advance.
Solution 1:[1]
Other than the animation part of your question. The onHover
argument of the InkWell
only works if you specify the onTap
argument first.
InkWell(
child: SomeWidget(),
onTap: () {
//You can leave it empty, like that.
}
onHover: (isHovering) {
if (isHovering) {
//The mouse is hovering.
} else {
//The mouse is no longer hovering.
}
}
)
From the documentation, here's the benefit of the boolean
, which is passed to the onHover
callback:
The value passed to the callback is true if a pointer has entered this part of the material and false if a pointer has exited this part of the material.
Solution 2:[2]
This is just a demo to show that you can use onHover
of Inkwell
widget to accomplish the task. You will have to come up with the logic to decide how much offset and scale should be used and how to position the widget. In my example I have used a grid view. You can perhaps use a stack to set the currently active widget based on the hover.
Here is the example with a grid view. The live version of this is available in this dartpad.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 3,
children: <Widget>[ImageHover(),ImageHover(),ImageHover(),ImageHover(),ImageHover(),ImageHover(),ImageHover(),],
);
}
}
class ImageHover extends StatefulWidget {
@override
_ImageHoverState createState() => _ImageHoverState();
}
class _ImageHoverState extends State<ImageHover> {
double elevation = 4.0;
double scale = 1.0;
Offset translate = Offset(0,0);
@override
Widget build(context) {
return InkWell(
onTap: (){},
onHover: (value){
print(value);
if(value){
setState((){
elevation = 20.0;
scale = 2.0;
translate = Offset(20,20);
});
}else{
setState((){
elevation = 4.0;
scale = 1.0;
translate = Offset(0,0);
});
}
},
child: Transform.translate(
offset: translate ,
child: Transform.scale(
scale: scale,
child: Material(
elevation: elevation,
child: Image.network(
'https://i.ytimg.com/vi/acm9dCI5_dc/maxresdefault.jpg',
),
),
),
),
);
}
}
Solution 3:[3]
Just create an extension
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
extension HoverExtension on Widget {
Widget get translateOnHover {
return kIsWeb ? TranslateOnHover(child: this) : ThisContainer(child: this);
}
}
class ThisContainer extends StatelessWidget {
ThisContainer({this.child});
final child;
@override
Widget build(BuildContext context) {
return Container(child: child);
}
}
class TranslateOnHover extends StatefulWidget {
final Widget child;
TranslateOnHover({required this.child});
@override
_TranslateOnHoverState createState() => _TranslateOnHoverState();
}
class _TranslateOnHoverState extends State<TranslateOnHover> {
double scale = 1.0;
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (e) => _mouseEnter(true),
onExit: (e) => _mouseEnter(false),
child: TweenAnimationBuilder(
duration: const Duration(milliseconds: 200),
tween: Tween<double>(begin: 1.0, end: scale),
builder: (BuildContext context, double value, _) {
return Transform.scale(scale: value, child: widget.child);
},
),
);
}
void _mouseEnter(bool hover) {
setState(() {
if (hover)
scale = 1.03;
else
scale = 1.0;
});
}
}
And use it anywhere by calling
yourWidget.translateOnHover
Solution 4:[4]
It's sad that there's not a built-in feature already, given that Flutter extended to web also, but luckily there is a package for this: hovering 1.0.4
You just need to install the package running this command flutter pub add hovering
or adding hovering: ^1.0.4
to your dependencies. Then you can use HoverWidget
,HoverContainer
, HoverAnimatedContainer
, and some more. It's not perfect, but it's an easy way to do it, specially for not complicated animations.
You can check the official docs of the package for more info: https://pub.dev/packages/hovering
Solution 5:[5]
You could use InkWell passing an onHover method alongside Transform Widget inside of a StatefulWidget.
Down below you could see some code of mine. This is a widget that hovers depending on a bool parameter canHover
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tayan |
Solution 2 | Abhilash Chandran |
Solution 3 | Madhav Tripathi |
Solution 4 | parkorian |
Solution 5 | Evandro Junior |