Imitation mobile iphone QQ message Little Red dot animation 1

Source: Internet
Author: User

Objective

Accidentally found that the iphone QQ display message number of the small red dot can respond to action events, also someone asked me how to do this animation, here the realization of the idea of a simple description. In the implementation of the process, also found that the function did not see so simple, to do a complete animation effect requires a certain foundation. Therefore, this article will focus on the implementation of ideas, and will not achieve an identical effect.
Here is the iphone qq Little red dot action interaction effect:

Analysis

First we analyze the performance of the drag-and-drop:

    1. The original Little red dot moves along the finger and connects with the original position through a small tail (i.e. a moving trajectory)
    2. With the original position within a certain range, the small tail appears; a small tail does not appear when it exceeds a certain range.
    3. Release your finger, the little red dot goes back to its original position and has a spring animation effect
    4. Release the finger from the original position beyond a certain range will not return to the origin, but there is a disappearing bubble animation

Leaving out the details and grabbing the gist, I summed up a few points:

    1. Small origin points move with your finger
    2. Small tail in the presence of
    3. When the finger is released, the Little red dot bounces back to its original position.

In addition, the red dots on the text, disappear and other situations of treatment is not the main problem, we first slow down.

Realize the movement of red dots

First, a circular view is implemented and can be moved in handy. Within a certain range of movement, when the finger leaves, the view returns to its original place with a spring effect, and the view stays at the left of the finger.
We draw a circle by DrawRect: To set a Cgpoint object to record where the touch begins, and then to implement the relevant touchevent:. Because all is very basic content, directly on the code.

//header File@interfaceZzspringview:uiview-(Instancetype) Initwithsquarelength: (cgfloat) Length originpoint: (cgpoint) opoint;@end//class fileConstCGFloat Koffset =100.0;//Drag the range limit@interfaceZzspringview () {cgpoint pointorigincenter;}@end@implementationZzspringview-(Instancetype) initWithFrame: (cgrect) frame{if(self =[Super Initwithframe:frame]) {Pointorigincenter=Self.center; Self.backgroundcolor=[Uicolor Clearcolor]; }    returnSelf ;}-(Instancetype) Initwithsquarelength: (cgfloat) Length originpoint: (cgpoint) opoint{if(self =[Self Initwithframe:cgrectmake (opoint.x, opoint.y, length, length)]) {    }    returnSelf ;}//Only override Drawrect:if perform custom drawing.//An empty implementation adversely affects performance during animation.- (void) DrawRect: (cgrect) rect {//Drawing CodeCgcontextref context =Uigraphicsgetcurrentcontext (); Cgcontextsetallowsantialiasing (Context,true); Cgcontextsetshouldantialias (Context,true);    Cgcontextaddellipseinrect (context, rect); Cgcontextsetfillcolorwithcolor (context, [Uicolor Redcolor].    Cgcolor); Cgcontextfillpath (context);}-(BOOL) _isdistanceenough: (cgpoint) point{cgfloat distance= (point.x-pointorigincenter.x) * (point.x-pointorigincenter.x) + (POINT.Y-POINTORIGINCENTER.Y) * (Point.y-pointorigincenter.y); if(Distance > Koffset *Koffset) {        returnYES; }    returnNO;}//Touch Event- (void) Touchesbegan: (Nsset *) touches withevent: (Uievent *)Event{Uitouch*touch =[touches anyobject]; Pointorigincenter=[Touch LocationInView:self.superview]; [UIView animatewithduration:.3animations:^{Self.center=Pointorigincenter; }];}- (void) touchescancelled: (Nsset *) touches withevent: (Uievent *)Event{}- (void) touchesmoved: (Nsset *) touches withevent: (Uievent *)Event{Uitouch*touch =[touches anyobject]; Cgpoint Pointmove=[Touch LocationInView:self.superview]; Self.center=Pointmove;} - (void) touchesended: (Nsset *) touches withevent: (Uievent *)Event{Uitouch*touch =[touches anyobject]; Cgpoint Pointend=[Touch LocationInView:self.superview]; CGFloat distance= (pointend.x-pointorigincenter.x) * (pointend.x-pointorigincenter.x) + (POINTEND.Y-POINTORIGINCENTER.Y) * ( POINTEND.Y-pointorigincenter.y); if([self _isdistanceenough:pointend]) {//May is destory self animationSelf.center =Pointend; Pointorigincenter=Self.center; }    Else{[UIView animatewithduration:1.0delay:.0usingspringwithdamping:0.1initialspringvelocity:.0Options:0Animations:^{Self.center=Pointorigincenter; } Completion:^(BOOL finished) {}]; }}
Zzsrpingview

In the Touchbegin event, because the location of the Little red dot is offset from the center, make a smooth transition through the UIView animation. In the Touchend event, the effect of returning a spring shock is to use the UIView spring animation.

Add a small tail (trajectory)

I drew a diagram of a simplified simulation drag-and-drop process:

The dashed circle is the view's original position, the P0 is its dot, the solid line circle is the moving position, and the P1 is the dot. Set the tangent of the two circle (red) and fill the enclosed part with the same color, and you can roughly simulate similar effects. There are a few prerequisites implied here:

    1. The actual trajectory is a curve with radians, where the tangent is used instead (the red tangent)
    2. When dragging, the original position of the circle view will be smaller with the drag distance, which is set to a fixed-size circle (the radius of the original half)

In view of this, we need to find the position of the two tangent points so that it becomes a closed shape to fill. At the same time, a small circle in the dashed position is filled. In this way, a similar function is basically done.
First we need to expand the scope of the current context, for simplicity, by adding the tail of the sub-view to the solid line, so that the original red dot view can be used. We now know the P0,P1, as well as the respective radii, and then we find the position and length of the periphery rectangle. Because it can be dragged in any direction, according to the current calculation, there are four kinds of situations to discuss. According to the Cartesian coordinate system, the legend is the first quadrant case. The same is possible with 234. In order to quickly verify the feasibility of the scheme, only the first quadrant is discussed and simulated.
To define a new view:

typedefenum: Nsuinteger {ZZLineDirection1=1,//NortheaseZZLineDirection2,//NorthwestZZLineDirection3,//SouthwestZZLineDirection4//Southeast} zzlinedirection;@interfaceZzspringtailview:uiview@property (nonatomic, assign) zzlinedirection linedirection; @property (nonatomic, assign) CGFloat radius;//Centerradius@property (nonatomic, assign) cgfloat Moveradius;@end
Zzspringtailview

Zzlinedirection represents a quadrant, radius is the radius of P0, Moveradius is the P1 radius. We add a view to the Touchmove event, before which we add an Zzspringtailview instance to the Zzspringview for internal access. The implementation of Touchmove is updated to:

- (void) touchesmoved: (Nsset *) touches withevent: (Uievent *)Event{Uitouch*touch =[touches anyobject]; Cgpoint Pointmove=[Touch LocationInView:self.superview]; if([self _isdistanceenough:pointmove]) {//beyond the offset, hide the view        if(Tailview) {Tailview.hidden=YES; }    }    Else    {        //Redraw the ViewSelf.center =Pointmove; if(!Tailview) {Tailview=[[Zzspringtailview alloc] init];        [Self addsubview:tailview]; } cgfloat widthhalf= self.bounds.size.width/2.0; CGFloat MinX=0;//= MIN (pointmove.x, pointorigincenter.x);CGFloat miny =0;//= MIN (Pointmove.y, pointorigincenter.y);CGFloat radius =widthhalf; //The width:the distance betweent the points and the origin size ' s WIDTH/2CGRect frameinsuper = CGRectMake (MinX, Miny, FABSF (pointmove.x-pointorigincenter.x) + widthhalf + radius, FABSF (pointMo VE.Y-POINTORIGINCENTER.Y) + Widthhalf +radius); Tailview.radius= radius/2; Tailview.moveradius=radius; if(pointmove.x >= pointorigincenter.x && pointmove.y <=pointorigincenter.y) {NSLog (@"Direnction1"); Tailview.linedirection=ZZLineDirection1; Frameinsuper.origin.x= Pointorigincenter.x-radius; FRAMEINSUPER.ORIGIN.Y= Pointmove.y-radius; }        Else if(pointmove.x <= pointorigincenter.x && pointmove.y <=pointorigincenter.y) {NSLog (@"Direnction2"); Tailview.linedirection=ZZLineDirection2; Frameinsuper.origin.x=pointmove.x; FRAMEINSUPER.ORIGIN.Y=pointmove.y; }        Else if(pointmove.x <= pointorigincenter.x && pointmove.y >=pointorigincenter.y) {NSLog (@"Direnction3"); Tailview.linedirection=ZZLineDirection3; Frameinsuper.origin.x= pointmove.x-radius; FRAMEINSUPER.ORIGIN.Y=Pointorigincenter.y; }        Else{NSLog (@"Direnction4"); Tailview.linedirection=ZZLineDirection4; Frameinsuper.origin.x= Pointorigincenter.x-radius; FRAMEINSUPER.ORIGIN.Y= Pointorigincenter.y-radius; } tailview.frame=[self convertrect:frameinsuper fromView:self.superview];    [Tailview Setneedsdisplay]; }}
touchmoveevent:

The implementation here is to add Tailview to the Springview, typically, cliptobouds default is no, so this addition is possible beyond the parent view bound Child view scheme. Note that the two point above is within the parent view of Spring view, so you need to convert to Springview's coordinate system when you finalize the Tailview frame.
The next step is Tailview's drawrect implementation. Here are 2 main things to do:

    1. Draw a circle with the center of the P0
    2. Draw a closed graphic of 2 tangent points

Partial implementations of the DrawRect:

- (void) DrawRect: (cgrect) rect{cgcontextref context=Uigraphicsgetcurrentcontext (); Cgcontextsetallowsantialiasing (Context,true); Cgcontextsetshouldantialias (Context,true); Cgcontextsetstrokecolorwithcolor (context, [Uicolor Greencolor].    Cgcolor); Cgcontextsetfillcolorwithcolor (context, [Uicolor Redcolor].    Cgcolor); Cgcontextsetlinewidth (Context,2); Cgpoint Pointstart, Pointend;//Centercgpoint movePoint1, MovePoint2;//Move 2 tangent points of a circleCgpoint CenterPoint1, CenterPoint2;//2 Tangent points of the original circleCGFloat Moveradius = _moveradius;//move the radius of an arccgfloat Sinval=0, Csinval =0; CGFloat distance=0; Switch(_linedirection) { CaseZZLineDirection1: {pointstart= Cgpointmake (Rect.size.width-moveradius,0+Moveradius); Pointend= Cgpointmake (0+ _radius, Rect.size.height-_radius); Distance= Cgrectgetheight (Rect) * Cgrectgetheight (Rect) + cgrectgetwidth (rect) *cgrectgetwidth (rect); Sinval= Cgrectgetheight (Rect) * cgrectgetheight (RECT)/distance; Csinval= Cgrectgetwidth (Rect) * Cgrectgetwidth (RECT)/distance; MovePoint2= Cgpointmake (Pointstart.x-moveradius * sinval, pointstart.y-moveradius*csinval); MovePoint1= Cgpointmake (Pointstart.x + moveradius*sinval, Pointstart.y + moveradius*csinval); CenterPoint2= Cgpointmake (pointend.x + _radius*sinval, Pointend.y + _radius*csinval); CenterPoint1= Cgpointmake (Pointend.x-_radius * sinval, Pointend.y-_radius*csinval);  Break; }         CaseZZLineDirection2: { Break; }         CaseZZLineDirection3: { Break; }         CaseZZLineDirection4: { Break;    }} cgcontextmovetopoint (context, movepoint1.x, movepoint1.y);    Cgcontextaddlinetopoint (context, movepoint2.x, movepoint2.y);    Cgcontextaddlinetopoint (context, centerpoint1.x, centerpoint1.y);    Cgcontextaddlinetopoint (context, centerpoint2.x, centerpoint2.y);    Cgcontextclosepath (context);    Cgcontextfillpath (context);    Cgcontextstrokepath (context); Cgcontextaddarc (context, pointend.x, Pointend.y, _radius,0,2*M_PI,0); Cgcontextfillpath (context);}
Zzspringtailview

The calculation process is not described in detail, Junior high School mathematics knowledge is enough. Then run and see the effect.

From the running effect, it is still passable. This shows the feasibility of the scheme.
Then the corresponding 234 quadrant situation can do similar processing, there is no code.

Due to the time of the relationship, temporarily study this, the next article will gradually improve the function. It will include the situation of adding text, etc., please look forward to.
If there is a better way to achieve, please enlighten us!

Imitation mobile iphone QQ message Little Red dot animation 1

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.