🥦 Introduction – About Bezier curves
Bezier curve, this is a term that we’re all familiar with, especially in the front end, if you haven’t used it.
And I’m going to continue to talk a little bit about bezier curves:
Bezier curve is such a curve, it is a smooth curve drawn from the coordinates of four arbitrary points. In history, people who studied Bessel curves originally designed this vector curve drawing method based on the idea that four points were determined by the known parametric equation of the curve. Bessel curves are more interesting because of their “rubber band effect”, which means that as points move regularly, the curve will produce a change like rubber band extension, which brings a visual impact. In 1962, French mathematician Pierre Bezier was the first to study this vector curve drawing method, and gave a detailed calculation formula, so the curve drawn according to such a formula is named after his family name is Bezier curve. -Baidu.com
His appearance laid the foundation for computer vector graphics, so what can we do with it?
Some people said, a lot of online search, this is necessary, “wave shape”, “parabolic effect” and so on.
🍋 Effect and calculation formula of Bezier curve
I’m not going to talk about the difference between Bessel curves, but I’m going to post the effect and the formula.
First order Bezier curve
Second order Bezier curve
Third order Bezier curve
The rest of the higher order, which I will not repeat, can be inferred as follows:
🥝 to achieve goods add shopping cart effect
After reviewing the principles of bezier curves, let’s look at what we are going to achieve today:
Before the implementation
Before we do that, let’s make sure that we use a second-order Bezier curve to achieve the parabolic effect.
Parameters needed for second-order Bessel curve:
- The starting point p0
- The control points p1
- At the end of the p2
How to get the coordinate points first forget, then look at the picture, there is a very important place, is according to the parabola falling together with the “little red point”.
How should the “little red dot” appear? Let’s move on.
Begin to implement
Let’s start with the above image. Where to start?
1. Figure out where you start and where you finish
The page is very simple and the code is as follows:
Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Row(
// Hide useless code
);
},
itemCount: 100,
),
),
Container(
height: 1,
color: Colors.grey.withOpacity(0.5),
),
Container(
height: 60,
color: Colors.white,
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20),
child: Icon(
Icons.shop_two,
key: _key,
),
)
],
),
)
],
)
Copy the code
A Column with a ListView at the top followed by a “shopping cart icon”.
The starting point is the + sign for each item in our ListView and the ending point is the “shopping cart icon” in the lower left corner.
The coordinates of the destination are easy to say, given a GlobalKey, then get the position in the first frame callback:
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((c) {
// Get the location of the shopping cart
_endOffset = (_key.currentContext.findRenderObject() as RenderBox)
.localToGlobal(Offset.zero);
});
}
Copy the code
What about the starting point?
Because the starting point is in the ListView and scrolling, many kids might say, “Why not give each icon a GlobalKey?
Are you sure you’re not killing me, kid?
GlobalKey uses a static constant Map to hold its corresponding Element. GlobalKey allows you to find the Widget, State, and Element that holds the GlobalKey. Note: GlobalKey is very expensive and should be used with caution.
– Vadaski – Flutter | a simple Key
If there were 10,000 listings at this point, wouldn’t it explode?
If we look at the code that fetched the location of the “shopping cart”, we are using the GlobalKey to fetch the context. If we use the context to fetch the location, why don’t we just use a component with the context?
The code is as follows:
Builder(
builder: (context) {
return IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: () {
// Use the Builder component to get the context
RenderBox box = context.findRenderObject();
varoffset = box.localToGlobal(Offset.zero); }); },)Copy the code
Use the Builder directly to get the location of the component.
So we have the coordinates of where we start and where we end, what about the control points?
2. Set the control points of second-order Bezier curves
So that’s a little bit easier, and we can look at this:
(Hand broken painting, just look)
We can play this control point at will, depending on the effect of your decision, here is the following:
var x1 = widget.startPosition.dx - 250;
var y1 = widget.startPosition.dy - 100;
Copy the code
We have all the values we need for a second-order Bezier curve, and now we can figure out where we are.
3. Obtain the position of the red dot in each frame
We have the values of P0, P1, and P2. We can use the Tween of the Flutter to obtain the value of t. Finally, we can insert the formula:
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(milliseconds: 800), vsync: this);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller);
// Second order Bezier curve
var x0 = widget.startPosition.dx;
var y0 = widget.startPosition.dy;
var x1 = widget.startPosition.dx - 250;
var y1 = widget.startPosition.dy - 100;
var x2 = widget.endPosition.dx;
var y2 = widget.endPosition.dy;
_animation.addListener(() {
// t dynamically changing value
var t = _animation.value;
if (mounted)
setState(() {
left = pow(1 - t, 2) * x0 + 2 * t * (1 - t) * x1 + pow(t, 2) * x2;
top = pow(1 - t, 2) * y0 + 2 * t * (1 - t) * y1 + pow(t, 2) * y2;
});
});
// Initialize the position of the dot
left = widget.startPosition.dx;
top = widget.startPosition.dy;
// The animation starts when the dot is displayed
_controller.forward();
}
Copy the code
After the animation starts, you can get the position of the little red dot for each frame.
4. Show the little red dot
How do I show the little red dot? So what do you have to do when you click.
The first thing THAT came to my mind was to wrap IndexStack around it, set the position of the little red dot when I clicked on it, and then display it.
Then Overlay 😂 came to mind.
The code for the Button in the ListView is as follows:
IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: () {
// Get the location of the current widget when clicked, passing in the overlayEntry
var _overlayEntry = OverlayEntry(builder: (_) {
RenderBox box = context.findRenderObject();
var offset = box.localToGlobal(Offset.zero);
return RedDotPage(
startPosition: offset,
endPosition: _endOffset,
);
});
/ / display Overlay
Overlay.of(context).insert(_overlayEntry);
// Wait for the animation to end
Future.delayed(Duration(milliseconds: 800), () {
_overlayEntry.remove();
_overlayEntry = null; }); },)Copy the code
The RedDotPage is the page we defined as a little red dot, we pass it the starting point, we make the Overlay display, and when the Overlay is displayed, we start the bezier curve animation, and when the animation is over, we remove the OverlayEntry.
🍍 summary
This is all about adding a shopping cart with the Flutter implementation, with some details in it.
The code has been submitted to Github – Add Shopping cart Demo.
If there are defects, I hope you put forward, learn together! 🤝