In the basic graph of path, in the previous article, we learned about the basic use of path, this time understanding the very very very important content in path-Bezier curve.
One. Path Common method table
For compatibility (lazy) This table removes the addition of API21 (i.e. Android version 5.0). Can not help but spit groove, why seems to be able to write some of the overloaded method to wait until API21 to add AH. The baby's heart is collapsing at the moment.
Action-related method notes
Move start MoveTo Move the start position of the next operation
Set End Setlastpoint Resets the last point position in the current path, and if called before drawing, the effect and moveto are the same
Connect line LineTo Add a line from the previous point to the current point to Path
Closed path Close connects the first point to the last point, forming a closed area
Add content Addrect, Addroundrect, Addoval, Addcircle, Addpath, AddArc, arcto Add (Rectangle, rounded rectangle, ellipse, circle, Path, ARC) to the current path (note the area of AddArc and ArcTo Don't
Whether null IsEmpty determines if path is empty
Whether the path is a rectangle or not is a rectangle isrect
Replace path set replaces all contents of the current path with a new path
Offset path offset offsets the operation before the current path (does not affect subsequent operations)
Bezier curve Quadto, Cubicto Two and three Bezier curves respectively
Rxxx method Rmoveto, Rlineto, Rquadto, Rcubicto method without R is based on the origin of the coordinate system (offset), the Rxxx method is based on the current point coordinate system (offset)
Fill mode Setfilltype, Getfilltype, Isinversefilltype, toggleinversefilltype settings, get, judge and toggle fill mode
Hint Method Increserve indicates how many points of path are waiting to be added (this method seems to allow path to optimize the storage structure)
Boolean operation (API19) Op boolean operation on two path (i.e., intersection, set, etc.)
Calculate boundary computebounds Calculate the boundary of path
Reset path Reset, rewind clears the contents of path
Reset does not retain the internal data structure, but it retains the filltype.
Rewind retains the internal data structure, but does not retain the Filltype
Matrix Operation Transform Matrix transformation
Two. Path explanation
In addition to some of the usual functions, the explanation is basically straight line, this time need to understand the curve part, when it comes to the curve, we have to mention the famous Bezier curve. Its inventor is the following man (French mathematician Pierrebézier).
What can a Bezier curve do?
Bezier curves are widely used, and it can be said that the Bezier curve lays the groundwork for computer graphics (because it can describe any complex graphic in a precise mathematical language), which you have used inadvertently.
If you use Photoshop, you may notice that there is a pen tool in it, and the core of the pen tool is the Bezier curve.
You say you can't PS? It's okay, if you've seen the previous article or used 2D drawings, you must have drawn circles, arcs, rounded rectangles and so on. The arcs in this section are all used in Bezier curves.
The Bezier curve acts very extensively and simply lifts a few chestnuts:
QQ Small red dot drag effect
Some cool drop-down refresh controls
Read the software's book-flipping effect
The making of some smooth line charts
A lot of cool animation effects
How do I easily get started with Bezier curves?
Although the use of Bezier curve is very wide, but there seems to be no suitable Chinese course, can search out Android about Bezier Chinese articles can be divided into the following:
Popular Science type (just let people understand Bessel, and there is no substantive content)
Loading force type (put a lot of formulas, quoting a bunch of English original)
Basic type (only two function usages that explain Bezier curves)
Actual combat type (according to the example of the application of Bezier curve)
The above several types of useful is the basic and actual combat type, but both have shortcomings, this article will synthesize the content of the two, starting from scratch to learn the Bezier curve.
First step. Understanding the principles of Bezier curves
The understanding of Bezier curves here is not a process of learning the derivation of formulas (?ω?), but about how Bezier curves are generated. Bezier curves use a series of points to control the state of the curve, and I divide the points into two simple categories:
Type action
Data points determine the starting and ending positions of a curve
Control points determine how curved the curve is
Here, for the time being, the concept is understood, and the detailed meanings are explained in the following.
First-order curve principle:
The first order curve is no control point, only two data points (A and B), the final effect of a segment.
Represents a stage in the first-order curve generation process, and dynamic processes can be referenced (the dynamic presentation of the Bezier curve in this article is from Wikipedia).
PS: The first-order curve is actually the lineto that was previously explained.
Second-order curve principle:
The second-order curve consists of two data points (A and C), a control point (B) describing the curve state, roughly as follows:
The red curve part is the legendary quadratic Bezier curve, so how is this red curve generated? Next we'll analyze it in one of these states:
Connect AB BC and take point E on the AB D,BC to meet the conditions:
Connect de, take point F, make:
The point F that gets to this is a point on the Bezier curve, and the dynamic process is as follows:
PS: The second-order curve corresponds to the method is Quadto
Sankai Curve principle:
The Sankai curve describes the curve state by two data points (A and D) and two control points (B and C), as follows:
The Sankai curve calculation process is similar to the second order, which can be seen in dynamic effect:
PS: Sankai curve corresponds to the method is Cubicto
Bézier Curve quick Look table
It is highly recommended to practice Bezier curves here to deepen the understanding of Bezier curves.
The second step is to understand how Bezier curve correlation functions are used
First-order curve:
The first order curve is a line segment, very simple, you can see the previous article path of the basic operation, here is not explained in detail.
Second Order curve:
With a simple understanding of the second order curve above, we know that the second order curve is composed of two data points and a control point, and then we use an example to demonstrate how the second order curve is used.
First of all, two data points are the position to control the start and end of the Bezier curve, it is easier to understand, while the control point is controlled Bezier bending state, relatively difficult to understand, so this example is focused on understanding Bezier curve bending State and control points of the relationship, not much to say, first:
In order to make it easier to see the relationship between the control point and curve bending degree, the auxiliary points and auxiliary lines are drawn, from the dynamic graph above, we can see that the Bezier curve has the same elastic effect as the rubber band in the process of dynamic change, so it is often used when making some elastic effects.
The main code is as follows:
public class Bézier extends View {
Private Paint Mpaint;
private int CenterX, centery;
Private PointF start, end, control;
Public Bessel1 (Context context) {
Super (context);
Mpaint = new Paint ();
Mpaint.setcolor (Color.Black);
Mpaint.setstrokewidth (8);
Mpaint.setstyle (Paint.Style.STROKE);
Mpaint.settextsize (60);
start = new PointF (0,0);
end = new PointF (0,0);
Control = new PointF (0,0);
}
@Override
protected void onsizechanged (int w, int h, int oldw, int oldh) {
Super.onsizechanged (W, H, OLDW, OLDH);
CenterX = W/2;
CenterY = H/2;
Initialize the location of data points and control points
Start.x = centerX-200;
Start.y = CenterY;
End.X = centerx+200;
End.y = CenterY;
control.x = CenterX;
Control.y = centerY-100;
}
@Override
public boolean ontouchevent (Motionevent event) {
Updates control points based on touch location and prompts to redraw
control.x = Event.getx ();
Control.y = Event.gety ();
Invalidate ();
return true;
}
@Override
protected void OnDraw (canvas canvas) {
Super.ondraw (canvas);
Plotting data points and control points
Mpaint.setcolor (Color.gray);
Mpaint.setstrokewidth (20);
Canvas.drawpoint (Start.x,start.y,mpaint);
Canvas.drawpoint (End.x,end.y,mpaint);
Canvas.drawpoint (Control.x,control.y,mpaint);
Draw Guides
Mpaint.setstrokewidth (4);
Canvas.drawline (Start.x,start.y,control.x,control.y,mpaint);
Canvas.drawline (End.x,end.y,control.x,control.y,mpaint);
Draw Bezier Curves
Mpaint.setcolor (color.red);
Mpaint.setstrokewidth (8);
Path PATH = new Path ();
Path.moveto (START.X,START.Y);
Path.quadto (CONTROL.X,CONTROL.Y,END.X,END.Y);
Canvas.drawpath (path, mpaint);
}
}
Sankai curve:
The Sankai curve controls the curve state by two data points and two control points.
Code:
public class Bezier2 extends View {
Private Paint Mpaint;
private int CenterX, centery;
Private PointF start, end, Control1, control2;
Private Boolean mode = TRUE;
Public Bezier2 (Context context) {
This (context, NULL);
}
Public Bezier2 (context context, AttributeSet Attrs) {
Super (context, attrs);
Mpaint = new Paint ();
Mpaint.setcolor (Color.Black);
Mpaint.setstrokewidth (8);
Mpaint.setstyle (Paint.Style.STROKE);
Mpaint.settextsize (60);
start = new PointF (0, 0);
end = new PointF (0, 0);
Control1 = new PointF (0, 0);
Control2 = new PointF (0, 0);
}
public void SetMode (Boolean mode) {
This.mode = mode;
}
@Override
protected void onsizechanged (int w, int h, int oldw, int oldh) {
Super.onsizechanged (W, H, OLDW, OLDH);
CenterX = W/2;
CenterY = H/2;
Initialize the location of data points and control points
Start.x = centerX-200;
Start.y = CenterY;
End.X = CenterX + 200;
End.y = CenterY;
control1.x = CenterX;
Control1.y = centerY-100;
control2.x = CenterX;
Control2.y = centerY-100;
}
@Override
public boolean ontouchevent (Motionevent event) {
Updates control points based on touch location and prompts to redraw
if (mode) {
control1.x = Event.getx ();
CONTROL1.Y = Event.gety ();
} else {
control2.x = Event.getx ();
Control2.y = Event.gety ();
}
Invalidate ();
return true;
}
@Override
protected void OnDraw (canvas canvas) {
Super.ondraw (canvas);
Drawcoordinatesystem (canvas);
Plotting data points and control points
Mpaint.setcolor (Color.gray);
Mpaint.setstrokewidth (20);
Canvas.drawpoint (Start.x, Start.y, Mpaint);
Canvas.drawpoint (End.X, End.y, Mpaint);
Canvas.drawpoint (control1.x, Control1.y, Mpaint);
Canvas.drawpoint (control2.x, Control2.y, Mpaint);
Draw Guides
Mpaint.setstrokewidth (4);
Canvas.drawline (Start.x, Start.y, control1.x, Control1.y, Mpaint);
Canvas.drawline (control1.x, control1.y,control2.x, Control2.y, Mpaint);
Canvas.drawline (control2.x, Control2.y,end.x, End.y, Mpaint);
Draw Bezier Curves
Mpaint.setcolor (color.red);
Mpaint.setstrokewidth (8);
Path PATH = new Path ();
Path.moveto (Start.x, START.Y);
Path.cubicto (control1.x, Control1.y, Control2.x,control2.y, End.X, END.Y);
Canvas.drawpath (path, mpaint);
}
}
The Sankai curve can make more complex shapes than the second-order curve, but for high-level curves, the combination of low-order curves can achieve the same effect, which is the legendary descending order. So our encapsulation of Bezier curves is generally up to Sankai curves.
Descending order and ascending order
Type interpretation change
Reducing the number of control points in order to maintain the shape and direction of the curve, that is, the reduction of the curve order method becomes simple, the data points become more, the control points may be reduced, the flexibility becomes weaker
In the case of maintaining the shape and direction of the curve, increase the number of control points, that is, the increasing curve order method is more complex, the data points are unchanged, the control points increase, flexibility becomes stronger
Step three. Bezier usage examples
Before making this instance, let's first clarify one thing, that is, under what circumstances will Bezier curves be used?
When you need to draw an irregular shape? Of course not! At present, I think the use of Bezier curve mainly has the following aspects (only personal humble opinion, there may be errors, please correct me)
Ordinal content use case
1 without prior knowledge of the curve state, a smooth line chart that requires real-time calculation of weather forecast temperature changes
2 display status will be changed according to user action qq Little red Dot, simulation book effect
3 Some more complex motion states (used with pathmeasure) animation effects of complex motion states
As for the situation where only a static curve graph is needed, it would be better to use a picture, and a lot of calculations would be very uneconomical.
If the SVG vector is displayed, there is already a relevant parsing tool (the Bezier curve is still used internally) and does not need to be calculated manually.
The main advantage of Bezier curve is that it can control the curve state in real time and make the curve smooth state change in real time by changing the state of the control point.
Next we'll use a simple example to make a circle gradient into a heart shape:
:
Thinking Analysis:
The effect of our final need is to transform a circle into a heart shape, and through analysis, the circle can be composed of four segments of the Sanche Besel curve, as follows:
The heart shape can also be composed of four segments of the three-order Bezier curve, as follows:
The difference between the two is that the data points and control points have different positions, so you only need to adjust the location of the data points and control points to change the circle to a heart shape.
Core difficulties:
1. How do I get the location of data points and control points?
about using the data points and control points to draw the circle has already been detailed calculation, you can refer to the StackOverflow of a answer how to create circle with Bézier curves? The data is only needed to be used.
And for the heart-shaped data points and control points, can be a circular part of the data points and control points to be translated, the specific parameters can be slowly adjusted to a satisfactory effect.
2. How do I achieve the gradient effect?
The gradient is actually each time the data points and control points slightly moved a little, and then redraw the interface, in a short time to adjust the data points and control points, so that it gradually close to the target value, through the continuous redrawing of the interface to achieve a gradient effect. The process can refer to dynamic effects:
Code:
public class Bezier3 extends View {
Private static final float C = 0.551915024494f; A constant used to calculate the position of the drawing point of a circular Bezier curve
Private Paint Mpaint;
private int Mcenterx, mcentery;
Private PointF Mcenter = new PointF (0,0);
Private float Mcircleradius = 200; Radius of the Circle
private float mdifference = mcircleradius*c; The difference between a circle's control point and the data points
Private float[] Mdata = new Float[8]; Four data points that draw a circle clockwise
Private float[] Mctrl = new FLOAT[16]; Eight control points that draw a circle clockwise
Private float mduration = 1000; Total length of change
private float mcurrent = 0; Current length of time
private float mCount = 100; How many copies of the duration are divided
private float mpiece = Mduration/mcount; The length of each serving
Public Bezier3 (Context context) {
This (context, NULL);
}
Public Bezier3 (context context, AttributeSet Attrs) {
Super (context, attrs);
Mpaint = new Paint ();
Mpaint.setcolor (Color.Black);
Mpaint.setstrokewidth (8);
Mpaint.setstyle (Paint.Style.STROKE);
Mpaint.settextsize (60);
Initializing data points
Mdata[0] = 0;
MDATA[1] = Mcircleradius;
MDATA[2] = Mcircleradius;
MDATA[3] = 0;
MDATA[4] = 0;
MDATA[5] =-mcircleradius;
MDATA[6] =-mcircleradius;
MDATA[7] = 0;
Initialize control points
Mctrl[0] = mdata[0]+mdifference;
MCTRL[1] = mdata[1];
MCTRL[2] = mdata[2];
MCTRL[3] = mdata[3]+mdifference;
MCTRL[4] = mdata[2];
MCTRL[5] = mdata[3]-mdifference;
MCTRL[6] = mdata[4]+mdifference;
MCTRL[7] = mdata[5];
MCTRL[8] = mdata[4]-mdifference;
MCTRL[9] = mdata[5];
MCTRL[10] = mdata[6];
MCTRL[11] = mdata[7]-mdifference;
MCTRL[12] = mdata[6];
MCTRL[13] = mdata[7]+mdifference;
MCTRL[14] = mdata[0]-mdifference;
MCTRL[15] = mdata[1];
}
@Override
protected void onsizechanged (int w, int h, int oldw, int oldh) {
Super.onsizechanged (W, H, OLDW, OLDH);
Mcenterx = W/2;
Mcentery = H/2;
}
@Override
protected void OnDraw (canvas canvas) {
Super.ondraw (canvas);
Drawcoordinatesystem (canvas); Drawing Coordinate systems
Canvas.translate (Mcenterx, mcentery); Move the coordinate system to the center of the canvas
Canvas.scale (1,-1); Flip Y-Axis
Drawauxiliaryline (canvas);
Draw Bezier Curves
Mpaint.setcolor (color.red);
Mpaint.setstrokewidth (8);
Path PATH = new Path ();
Path.moveto (mdata[0],mdata[1]);
Path.cubicto (Mctrl[0], mctrl[1], mctrl[2], mctrl[3], mdata[2], mdata[3]);
Path.cubicto (Mctrl[4], mctrl[5], mctrl[6], mctrl[7], mdata[4], mdata[5]);
Path.cubicto (Mctrl[8], mctrl[9], mctrl[10], mctrl[11], mdata[6], mdata[7]);
Path.cubicto (mctrl[12], mctrl[13], mctrl[14], mctrl[15], mdata[0], mdata[1]);
Canvas.drawpath (path, mpaint);
Mcurrent + = mpiece;
if (Mcurrent < mduration) {
MDATA[1]-= 120/mcount;
MCTRL[7] + = 80/mcount;
MCTRL[9] + = 80/mcount;
MCTRL[4]-= 20/mcount;
MCTRL[10] + = 20/mcount;
Postinvalidatedelayed ((long) mpiece);
}
}
Draw Guides
private void Drawauxiliaryline (canvas canvas) {
Plotting data points and control points
Mpaint.setcolor (Color.gray);
Mpaint.setstrokewidth (20);
for (int i=0; i<8; i+=2) {
Canvas.drawpoint (mdata[i],mdata[i+1], mpaint);
}
for (int i=0; i<16; i+=2) {
Canvas.drawpoint (Mctrl[i], mctrl[i+1], mpaint);
}
Draw Guides
Mpaint.setstrokewidth (4);
for (int i=2, j=2; i<8; i+=2, j+=4) {
Canvas.drawline (Mdata[i],mdata[i+1],mctrl[j],mctrl[j+1],mpaint);
Canvas.drawline (Mdata[i],mdata[i+1],mctrl[j+2],mctrl[j+3],mpaint);
}
Canvas.drawline (Mdata[0],mdata[1],mctrl[0],mctrl[1],mpaint);
Canvas.drawline (Mdata[0],mdata[1],mctrl[14],mctrl[15],mpaint);
}
Drawing Coordinate systems
private void Drawcoordinatesystem (canvas canvas) {
Canvas.save (); Draw to do coordinate system
Canvas.translate (Mcenterx, mcentery); Move the coordinate system to the center of the canvas
Canvas.scale (1,-1); Flip Y-Axis
Paint Fuzhupaint = new paint ();
Fuzhupaint.setcolor (color.red);
Fuzhupaint.setstrokewidth (5);
Fuzhupaint.setstyle (Paint.Style.STROKE);
Canvas.drawline (0, -2000, 0, Fuzhupaint);
Canvas.drawline ( -2000, 0, 0, fuzhupaint);
Canvas.restore ();
}
}
Three. Summary
In fact, the most important thing about Bezier curves is the core understanding of how Bezier curves are generated, and only by understanding how Bezier curves are generated can we better use Bezier curves. At the end of the previous article to refer to a little self-intersecting graphics rendering problems, unfortunately, this article did not, please look forward to the next (may appear in the next article O ( ̄︶ ̄) o), the next article is still the path related content, to teach you something better to play.
Unlock the new realm of "draw a circle of elasticity":
(,,• ? •,,)
PS: Due to my limited level, some places may be misunderstood or inaccurate, if you have questions about this can submit issues for feedback.
Android Custom View Advanced: Bezier curve