How to draw an oval speech bubble programmatically on iPhone?

The technique shown in a similar question is a rectangular bubble. How to draw one in an oval shape? i.e:.

enter image description here

+4
source share
2 answers

I would do it in two iterations.
First get the context and start the path. Fill an ellipse, and then a custom path that contains a triangle with three lines. I assumed the following sizes: 70 width, 62 height. Override draw rect in a subclass of UIView and create an instance in a subclass of UIViewController:

-(void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(ctx, 0.0, 0.0, 1.0, 1.0); CGContextFillEllipseInRect(ctx, CGRectMake(0.0, 0.0, 70.0, 50.0)); //oval shape CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, 8.0, 40.0); CGContextAddLineToPoint(ctx, 6.0, 50.0); CGContextAddLineToPoint(ctx, 18.0, 45.0); CGContextClosePath(ctx); CGContextFillPath(ctx); } 

It does this in the iPhone simulator when added to a gray background:

enter image description here

This second code example almost duplicates what you created above. I implemented this using flexible sizes that can be passed to the UIView frame when it is created. In fact, the white part of the speech bubble is drawn with a black stroke over the lying one to follow.

 -(void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGRect aRect = CGRectMake(2.0, 2.0, (self.bounds.size.width * 0.95f), (self.bounds.size.width * 0.60f)); // set the rect with inset. CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); //white fill CGContextSetRGBStrokeColor(ctx, 0.0, 0.0, 0.0, 1.0); //black stroke CGContextSetLineWidth(ctx, 2.0); CGContextFillEllipseInRect(ctx, aRect); CGContextStrokeEllipseInRect(ctx, aRect); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f)); CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f)); CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f)); CGContextClosePath(ctx); CGContextFillPath(ctx); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f)); CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f)); CGContextStrokePath(ctx); CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, 3.0, (self.bounds.size.height *0.80f)); CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f)); CGContextStrokePath(ctx); } 

enter image description here

+7
source

I have another way - however, I do not have time to correctly explain this.

However, my example was written in .NET for use in a Windows application.

My version creates an entire speech bubble in the form of a 2D Polygon Mesh and is partially customizable. This is one way back instead of several parts.

While our platforms do not match, the method uses common mathematical procedures and a procedural cycle. I believe that this technique can be translated into other programming languages ​​or platforms.

  Private Sub Generate(ByVal Resolution As Integer, Optional ByVal SpeachPointerAngle As Integer = (45 * 3), Optional ByVal PointerBend As Decimal = 15) 'Generated the same way we create vector (wireframe) mesh for an Ellipse but... '... at a predefined defined angle we create 'the size of the Pointer TIP/Corner portion of the speach bubble 'in relation to the EDGE of the ELLIPSE (average) Dim SpeachPointerSize As Integer = 30 If PointerBend > 10 Then PointerBend = 10 If PointerBend < -10 Then PointerBend = -10 'as a variable offset that should be limited to max +/- -15 to 15 degrees relative to current angle as a safe range '- were speach pointer angle determins which side the the pointer appears Dim PointerOffsetValue As Decimal = PointerBend Dim ActualPointerAngle As Decimal 'SpeachPointerAngle = 360 - SpeachPointerAngle ' adjust orientation so that 0 degrees is SOUTH 'Ellipse Size: Dim Size_X As Decimal = 80 Dim Size_Y As Decimal = 50 If Resolution < 30 Then Resolution = 30 Dim Result As Vector2() 'size of each angle step based on resolution (number of vectors ) - Mesh Quality in otherwords. Dim _Step As Decimal = 360 / Resolution 'Our current angle as we step through the loop Dim _CurrentAngle As Decimal = 0 'rounded values Dim _LastAngle As Decimal = 0 Dim _NextAngle As Decimal = _Step Dim SpeachDrawn As Boolean = False ' prevent creating more than 1 point to be safe Dim I2 As Integer = 0 'need a stepper because of skipped IDS 'build the ellipse mesh For i = 0 To Resolution - 1 _LastAngle = _CurrentAngle - 15 _NextAngle = _CurrentAngle + 15 ActualPointerAngle = _CurrentAngle 'side ActualPointerAngle += PointerOffsetValue ' acual angle of point Dim EX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * Size_X Dim EY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * Size_Y 'Point extrusion size ( trying to be even size all around ) Dim ExtrudeX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * (Size_X + SpeachPointerSize) Dim ExtrudeY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * (Size_Y + SpeachPointerSize) 'is Pointer angle between Last and Next? If SpeachPointerAngle > _LastAngle And SpeachPointerAngle < _NextAngle Then If (SpeachDrawn = False) Then ' the point for the speachbubble tip Array.Resize(Result, I2 + 1) Result(I2) = New Vector2(ExtrudeX, ExtrudeY) SpeachDrawn = True I2 += 1 Else 'skip End If Else 'normal ellipse vector Array.Resize(Result, I2 + 1) Result(I2) = New Vector2(EX, EY) I2 += 1 End If _CurrentAngle += _Step Next _Vectors = Result End Sub 

The above code generated this - drawn into a bitmap using GDI + [DrawPolygon / FillPolygon]: https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/380262_10151202393414692_590995900_n.jpg

(Sorry, I cannot post the image directly here, as I have never written here before. I have no reputation yet)

This is a primitive in the graphic assembly that I am developing for .NET that uses my own Vector2.

This speech bubble provides transparency when drawing - as it is one polygon shape instead of multiple shapes.

Basically, we draw an ellipse programmatically, and then extrude the selection point onto the desired side of the ellipse.

A similar approach can be applied using PointF structures.

All shapes in the code are generated around Origin 0,0.

Arrays also change in stages as vectors are added, preventing spaces in the array.

EG - center of speech bubble - Origin 0.0.

I apologize for not explaining my code correctly - I just don't have the time. But this is probably not too hard to understand.

0
source

All Articles