Custom Cursors in Flutter Web
A tricky way to make your widget into the Cursor in Web Browser :D
We are not actually changing the system cursor to another like in this blog, rather its a trick, we are hiding the real one and adding a widget to the current hover position.
We will be using one of the basic building Widget of Flutter to achieve this and that widget is Positioned. We’ll use AnimatedPositioned later for smooth user interaction, AnimatedPositioned is one of the ImplicitAnimatingWidget subclass, which generally respond to the changes in their Property with animation over a specified Duration.
Lets get started
First we need to wrap our scaffold’s body with MouseRegion widget, with it we can get the cursor position in real-time and it also have property named cursor
through which we can change the actual cursor or replace with other system cursors. And we also need a pointer variable to save that cursor’s realtime value.
In our case we will hide cursor and set pointer on Hover, like this :
Offset pointer = Offset.zero;
@override
Widget build(BuildContext context) {
return Scaffold(
body: MouseRegion(
cursor: SystemMouseCursors.none,
onHover: (eve) {
setState(() {
pointer = eve.position;
});
},
child: ...
),
);
}
Second step is to add a widget at the pointer
's position. For that we will use Stack
widget and Positioned
widget to position our custom made cursor in the stack. Make sure your stack have full width and height.
child : Stack(
children: [
Positioned(
left : ...
top : ...
),
OtherWidgetsIfAny(),
],
),
Now we need to add child to Positioned
widget, I made the simple Cursor with size 200 x 200 (its just a circular ring).
child : Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
border: Border.all(
width: 4,
color: Colors.white,
style: BorderStyle.solid)),
),
Now just one this is left i.e., to position this cursor. For that we will just use the dx
and dy
from the pointer offset. So the complete code should look like :
Positioned(
left: pointer.dx - 100,
top: pointer.dy - 100,
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
border: Border.all(
width: 4,
color: Colors.white,
style: BorderStyle.solid)),
),
),
Why -100
? you know it :)
Here is what your result till now should look like :
Here you go, you got yourself a custom Cursor in flutter web. But there is something missing? cursor movement is kind of stiff, right? Here comes the implicit animations part.
Just simply use AnimatedPositioned
widget instead of Positioned
and add duration to it.
AnimatedPositioned(
duration: const Duration(milliseconds: 500),
left: pointer.dx - 100,
top: pointer.dy - 100,
child:...
),
Here is the gist with all of the code we have used for this basic cursor.
Whats More?
Check out this Flutter pen on codepen.io for Live preview of the custom Cursor made with same technique.
Thank you and keep learning! ❤️