Custom Cursors in Flutter Web

Sahdeep Singh
Bobble Engineering
Published in
3 min readJul 27, 2020

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 :

Cursor following mouse pointer but hidden

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:...
),
Animated Positioned Cursor

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! ❤️

--

--