First, preface
Study is to summarize, in recent days to learn the drawing related, but the use of less opportunities, and now almost forgotten, this time to see the water ripple of the drawing, feel very interesting, or the realization of the method recorded. Technology without him, for hand-cooked, or to practice more, empty light endangers, hard work Hing bang, let us look at today's triangle function of the beauty bar.
Ii. Overview
Certainly everyone is not unfamiliar with the triangle function of middle school study, but the study of sin, cos is a function of transcendental function, is a kind of elementary function, borrowed a picture of Wikipedia:
A complete sine function should be this: >y=asin (ωx+φ) +h,a determines the peak, Ω determines the period, φ represents the initial phase, and H represents the position of the y-axis. In Android we use the general is Math.sin (30*math.pi/180) This form, I originally do not understand the meaning of this writing, later only understand Math.PI is π,π namely 180 degrees, so the above equation equivalent to sin (Π/6) =1/2, In high school we are generally sin (30°) =1/2, which assigns x in sin (x) as an angle, whereas in computer language x is usually radians.
This flow interface is through the SIN function curve constantly changing the x position to draw, the way of implementation certainly there are other methods, through the drawing Bezier curve also has the implementation of the case, we will use the example of the water ripple Loadingview drawing, well, not much to say, Hands-on take you step by step to achieve beautiful cool loading water ripple effect.
Three, the implementation of the Wave control
First, we first implement the rendering of the wave control:
Calculate the coordinate points first:
//这里我们以view的总宽度为周期,y = a * sin(2π) + b for (int0; i < mTotalWidth; i++){ mPointY[i] = (float) (20 * (Math.sin2 * Math.PI * i / w))); }
Drawing curves
fori0;ii++){ canvas.drawLine(i,mTotalHeight - mDaymicPointY[i] - 300,i,mTotalHeight,mPaint); }
Minus 300 here is to control the position on the y-axis, we can dynamically set a value, move up and down the view to reach the traffic interface, we first step.
Control movement
//改变两条波纹的移动点 mXoffset += X_SPEED; //如果已经移动到末尾处,则到头重新移动 if(mXoffset > mTotalWidth){ 0; }
// 超出屏幕的挪到前面,mXoffset表示第一条水波纹要移动的距离 int yIntelrval = mPointY.length - mXoffset; //使用System.arraycopy方式重新填充第一条波纹的数据 0, mDaymicPointY, mXoffset, yIntelrval); 0, mXoffset);
Now you will find a simple water ripple effect coming out as shown in:
You will find this water ripple with our effect is still some gap, don't worry, we also have this class Porterduffxfermode, can be implemented with the drawing of the image according to a certain rule to mix, to form a new pixel value, then we can draw a water ripple effect, and then draw a circle, Use the following diagram to mix, you will find a miracle, Porterduffxfermode related use can refer to this blog:
Porterduffxfermode use and working principle of canvas drawing in Android
What kind of rules to use, their own to find Bai, are to carry out some kind of rules to mix, I found, using the srcin, can be mixed to achieve the effect of
Now this is the effect, we are adding a seekbar, drag the display effect, basically can appear this wave loading effect
intCanvaswidth =Canvas. GetWidth ();intCanvasheight =Canvas. GetHeight ();intLayerid =Canvas. Savelayer (0,0, canvaswidth, canvasheight, NULL, Canvas.all_save_flag);Canvas. drawcircle (Mtotalwidth/2, Mtotalheight/2, Mtotalwidth/2, Mcriclepaint);//Set color blending modeMpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));//high minus width divided by 2 to make the water ripple bottom at the bottom of the circle, dynamically change the percent value, change on the y axis for(inti =0; i < mtotalwidth; i++) {Canvas. DrawLine (i, Mtotalheight-mdaymicpointy[i]-(mtotalheight-mtotalwidth)/2-percent* Mtotalwidth/ -, I, Mtotalheight-(mtotalheight-mtotalwidth)/2, Mpaint); }///finally remove the brush XfermodeMpaint.setxfermode (NULL);//Change the moving point of two ripplesMxoffset + = X_speed;//If you have moved to the end, the head is moved again if(Mxoffset > Mtotalwidth) {Mxoffset =0; }Canvas. Restoretocount (Layerid);
The effect is as shown
I put down all the code to implement the process:
Public class waveview extends View { PrivatePaint Mpaint, Mcriclepaint,mtextpaint;//Tilt or rotate, fast change, when a line is drawn on the screen, there is no aliasing, //But when you draw diagonally, you'll get jagged effects, so you'll need to set anti-aliasing PrivateDrawfilter Mdrawfilter;Private intMtotalheight, Mtotalwidth;Private intMxoffset =0;Private float[] mpointy;Private float[] mdaymicpointy;//Wave line movement speed Private Static Final intX_speed = -;Private intPercent Public void setpercent(intpercent) { This. percent = percent; } Public Waveview(Context context) {Super(context); Init (); } Public Waveview(context context, AttributeSet attrs) {Super(context, attrs); Init (); } Public Waveview(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); Init (); }Private void Init() {//Picture Line (Universal) anti-aliasing needs to be set separatelyMdrawfilter =NewPaintflagsdrawfilter (0, Paint.anti_alias_flag | Paint.filter_bitmap_flag);//Instantiate a brushMpaint =NewPaint ();//Remove brush aliasingMpaint.setantialias (true);//Set brush style to solid lineMpaint.setstyle (Paint.Style.FILL);//Set Brush colorMpaint.setcolor (Color.green);//Instantiate a circle brushMcriclepaint =NewPaint (Mpaint); Mcriclepaint.setcolor (Color.parsecolor ("#88dddddd")); Mcriclepaint.setalpha (255);//instanced text BrushMtextpaint =NewPaint (); Mtextpaint.setantialias (true); }@Override protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas);//antialiasingCanvas.setdrawfilter (Mdrawfilter); Runwave ();intCanvaswidth = Canvas.getwidth ();intCanvasheight = Canvas.getheight ();intLayerid = Canvas.savelayer (0,0, Canvaswidth, Canvasheight,NULL, Canvas.all_save_flag); Canvas.drawcircle (Mtotalwidth/2, Mtotalheight/2, Mtotalwidth/2, Mcriclepaint);//Set color blending modeMpaint.setxfermode (NewPorterduffxfermode (PorterDuff.Mode.SRC_IN));//high minus width divided by 2 to make the water ripple bottom at the bottom of the circle, dynamically change the percent value, change on the y axis for(inti =0; i < mtotalwidth; i++) {canvas.drawline (i, Mtotalheight-mdaymicpointy[i]-(mtotalheight-mtotalwidth)/2-percent * Mtotalwidth/ -, I, Mtotalheight-(mtotalheight-mtotalwidth)/2, Mpaint); }///finally remove the brush XfermodeMpaint.setxfermode (NULL);//Change the moving point of two ripplesMxoffset + = X_speed;//If you have moved to the end, the head is moved again if(Mxoffset > Mtotalwidth) {Mxoffset =0; } canvas.restoretocount (Layerid); String Text = percent +"%"; Mtextpaint.settextsize ( the);floatTextLength = Mtextpaint.measuretext (text); Canvas.drawtext (text, (mtotalwidth-textlength)/2, Mtotalheight/2- -, Mtextpaint);//Cause view redrawPostinvalidatedelayed ( -); }@Override protected void onsizechanged(intWintHintOLDW,intOLDH) {Super. onsizechanged (W, H, OLDW, OLDH); Mtotalheight = h; Mtotalwidth = W;//The length of the array is the width of the viewMpointy =New float[W]; Mdaymicpointy =New float[W];//Here we take the total width of the view as the period, y = a * sin (2π) + b for(inti =0; i < mtotalwidth; i++) {Mpointy[i] = (float) ( -* (Math.sin (2* Math.PI * i/w)); } }Private void Runwave() {//Beyond the screen to the front, mxoffset means the first water ripple to move the distance intYintelrval = Mpointy.length-mxoffset;//re-populate the first ripple data using the System.arraycopy methodSystem.arraycopy (Mpointy,0, Mdaymicpointy, Mxoffset, Yintelrval); System.arraycopy (Mpointy, Yintelrval, Mdaymicpointy,0, Mxoffset); }}
Above is the implementation of all the code, there are comments, I believe we can understand, in fact, to achieve these effects is very simple, but we also have a lot of expansion of the place, a network to load the waiting animation, or make a download of the progress, waiting for everyone to achieve.
Source code later upload
The beauty of trigonometric functions-water ripple loading Loadingview