similar question中显示的技术是矩形气泡。如何画一个椭圆形?即:
答案 0 :(得分:8)
我会在两次迭代中完成。
首先获取上下文并开始路径。填充椭圆,然后填充包含三行三角形的自定义路径。我假设以下尺寸:70宽度,62高度。覆盖UIView的子类中的draw rect并在子类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);
}
在灰色背景下添加时,在iPhone模拟器中生成此内容:
这第二个代码示例几乎会复制您在上面生成的内容。我使用灵活的大小实现了这个,当你实例化它时可以提供给UIView框架。基本上,讲话气泡的白色部分是用黑色笔划绘制的。
-(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);
}
答案 1 :(得分:0)
我有另一种方式 - 但我没有时间妥善解释它。
但是,我的示例是用.NET编写的,用于Windows应用程序。
我的版本将整个语音气泡创建为2D多边形网格,并且可以部分自定义。它是单个绘制路径而不是多个部分。
虽然我们的平台不一样 - 该技术使用常见的数学例程和程序循环。我相信这种技术可以翻译成其他编程语言或平台。
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
上面的代码生成了这个 - 使用GDI + [DrawPolygon / FillPolygon]绘制到位图: https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/380262_10151202393414692_590995900_n.jpg
(对不起 - 我不能直接在这里发布图片,因为我以前从未在这里发布。我还没有声誉)
这是我正在为.NET开发的图形程序集中的原语,它使用我自己的Vector2。
此Speach气泡在绘制时支持透明度 - 因为它是单个多边形形状而不是多个形状。
基本上我们以编程方式绘制椭圆,然后在椭圆的所需边上拉出一个说明点。
可以使用PointF结构来应用类似的方法。
代码中的所有形状都是在Origin 0,0周围生成的。
当添加矢量时,阵列也会逐渐调整大小,以防止阵列中的间隙。
EG - 说话气泡的中心是Origin 0.0。
我为没有正确解释我的代码而道歉 - 我只是没有时间。 但它可能不太难理解。