How To Draw A Speech Bubble
- Download demo - 20.69 KB
- Download source - 26.83 KB
Introduction
I was working on a Windows Forms project that required the user to be able to add together speech balloons (also known as speech bubbles) on top of photographs or drawings. As I'm somewhat adept with GDI+, I figured it wouldn't be also complicated; I'd either use a GraphicsPath
or a Region
. Ultimately, I wanted to draw the balloon, marriage information technology with a tail, fill the resulting shape, and depict its outline. I knew Region
had a Union
method, so I tried that ane first. The spousal relationship worked just fine, only while I was able to fill the combined shapes area with the background color, in that location is no Draw
method for regions in GDI+, thus I was unable to draw the outline of the speech balloon. If I tried to describe the outlines of the individual shapes using the two GraphicsPath
objects, the outlines would intersect with each other and not work at all.
I so tried GraphicsPath
, and while GDI+ has both Fill
and Describe
methods for it, there's no way to spousal relationship 2 GraphicsPath
objects into ane shape, and I was left with the same trouble for drawing the edge equally I was with Region
.
I as well looked into whether there'southward a way to convert from a Region
to a GraphicsPath
(in order to get a GraphicsPath
object from a unioned Region
), just there wasn't. At that point, I stopped trying to figure it out by myself, and vicious back on the programmer'south best friend, the Internet. Searching for solutions online (where I actually constitute a few people asking how to make voice communication balloons), the resounding respond was that you cannot exercise this due to the limitations of GDI+ and the Region
and GraphicsPath
classes (which I mentioned above). This article describes how I worked around the problem, and provides a sample awarding that you can employ to generate your own voice communication balloon images or generate the code required to replicate the airship you design.
Background
Anatomy of a Speech Balloon
To help make my code and the sample program a little easier to follow, I'one thousand going to provide some basic terminology. I've fabricated most of this stuff upwards in a way that makes sense to me, so to actual comic artists out there who know all the technical terms for these $.25 and pieces, I apologize if I'm not using the right names.
Regardless of what blazon of balloon (oral communication, thought, starburst) we're talking virtually, the central expanse is called the balloon. The protrusions around the perimeter of the balloon (bubbles for thought balloons, spikes or rays for the starbursts) I simply call bubbling. What's the difference between thought balloon bubbles and starburst bubbles, you might ask? The difference is that starburst bubbles are sharper than thought balloon bubbles. The single protrusion that points to the speaker (or thinker) of the airship, I call the tail.
Requirements
Drawing a speech balloon involves two parts: drawing the actual balloon itself (with its bubbles), and drawing the tail. Because I like to make things every bit generic and reusable equally possible, my spoken language balloon drawing system had to back up the following requirements:
- The ability to have any text in the balloon
- The power to specify the colors of the text, the balloon fill color, and the border color
- The ability to set the font used to draw the text
- The power to show or hibernate the border
- The ability to show or hide the tail
- The ability to change the size and orientation of the tail around the balloon
- The power to alter the shape of the balloon to simulate oral communication (ellipse), thought (bubbly ellipse), and actions (starburst)
The SpeechBalloon Grade
In my solution, I created a new form chosen SpeechBalloon
which holds all the backdrop of the speech airship nosotros can set, as well as the method for actually rendering the airship into a Graphics
object. I'yard not going to bother going into the details of pedestrian properties like Font
, Bounds
, BorderWidth
, etc., as they should be pretty self-explanatory and the code is well-commented.
The GraphicsPath
object that holds the shape of the balloon is stored in a read-simply property named Path
. I buffer the GraphicsPath
instead of re-creating it on each phone call to Depict
every bit information technology can exist a circuitous process (every bit we'll meet below). Each of the other properties, when changed, will crusade the path to be recreated (if the said property affects the airship's shape), and volition raise an event, RedrawRequired
, on the SpeechBalloon
instance to inform the parent programme that the oral communication balloon needs to exist redrawn on its drawing surface. Here are some examples:
This belongings changes the shape of the balloon and causes our lawmaking to regenerate its GraphicsPath
(via the RecreatePath
method):
Public Property Width() As Integer Become Return MyBounds.Width Terminate Get Set(ByVal value As Integer) Dim inverse As Boolean = value <> MyBounds.Width MyBounds.Width = value If changed Then RecreatePath() RaiseEvent RedrawRequired(Me, EventArgs.Empty) End If End Set End Property
This property does non alter the shape of the balloon (and thus only raises the RedrawRequired
event):
Private MyFillColor As Color = Color.White Public Holding FillColor() Equally Color Become Return MyFillColor End Go Gear up(ByVal value Equally Color) Dim changed Equally Boolean = value <> MyFillColor MyFillColor = value If inverse Then RaiseEvent RedrawRequired(Me, EventArgs.Empty) Stop Set up End Belongings
Creating the Balloon
The individual RecreatePath
method in the SpeechBalloon
class creates our balloon's GraphicsPath
buffer. To create the bubbling around the airship, we're going to look at three properties of the SpeechBalloon
course: BubbleWidth
, which specifies how many degrees broad a single chimera is on the perimeter of the airship; BubbleSize
, which determines how far from the balloon the bubbles protrude; and BubbleSmoothness
, which determines whether our bubbles will exist soft and curvy (as in idea balloons) or hard and sharp (equally in starbursts).
The first thing RecreatePath
does is clear the buffer:
Private Sub RecreatePath() Path.Reset()
If our BubbleSize
property is set to 0
, we have a elementary speech airship, and GraphicPath
'due south AddEllipse
method is all nosotros demand:
If BubbleSize = 0 Then Path.AddEllipse(0, 0, Width, Height)
Otherwise, we're going to have to exercise some work to make these bubbles. For each bubble, we need iii points: the starting point of the bubble forth the airship's ellipse, the ending point of the bubble along the balloon's ellipse, and a point between the two that is positioned abroad from the perimeter of the balloon (as determined by BubbleSize
).
I won't bore you with the loop details and trig required to summate those three points, but y'all can await at the code (which I've tried to annotate as best as I can) for more details. Suffice it to say that I was never that proficient at trigonometry, merely I learned enough to know how to find the formulae I needed online:
Else Dim theta Equally Integer = 0 For theta = 0 To (360 - BubbleWidth) Step +BubbleWidth Dim points(2) As Point points(0) = New Point(ten, y) points(1) = New Point(x2, y2) points(2) = New Signal(x3, y3) Path.AddCurve(points, BubbleSmoothness) Side by side Path.CloseAllFigures() End If Finish Sub
As you tin can see, the GraphicsPath.AddCurve
method takes a parameter that determines how curve-similar the resulting bend is. A value of 0.0 creates a triangular shape. A value of 1.0 creates a perfect curve. Annihilation greater than 1.0 does strange things (experience complimentary to experiment with my sample app).
Creating the Tail
To keep things simple, the only tail I support is a triangular one, and its drawing origin is located at the eye of the airship. There are three properties on the SpeechBalloon
class associated with the tail: TailLength
, which is the altitude from a perfectly vertical tail from the top of the airship; TailBaseWidth
(referred to every bit Tail Width in the sample app), which is the width of the base of the triangle; and TailRotation
, which determines at what angle around the speech balloon the tail is going to signal towards. I always draw an upward tail and use TailRotation
with Graphics.RotateTransform
to spin it into position.
Since tail creation is very elementary, I recreate the tail equally part of each call to the Draw
method on SpeechBalloon
:
tail.AddLine(-TailBaseWidth, 0, TailBaseWidth, 0) tail.AddLine(TailBaseWidth, 0, 0, -(TailLength + (Meridian \ 2))) tail.CloseFigure()
Putting information technology All Together
Now that I accept my balloon path and my tail path, I had to overcome the challenge of how I was going to fill and outline them both equally if they were i shape. After some trial and error, I discovered a relatively simple fashion to it:
- Draw the tail'south border, twice as thick as the airship's edge. When the airship is filled, it volition cover upwardly the part of the tail edge that is drawn under the airship itself.
- Make full the balloon'south path using the background colour.
- Draw the balloon'southward border.
- Make full the tail's path using the background colour. This ensures that the outer border of the balloon where it meets the tail is colored over with the background colour, giving the illusion that the tail and the balloon are all one big happy object, plus it covers up half of the tail's border (which we drew double-sized) to make it look as wide as the residue of the balloon'southward edge.
In lawmaking, that translates to the following:
If TailVisible AndAlso BorderVisible Then Dim thickPen Every bit New Pen(BorderColor, BorderWidth * 2.0) gstate = yard.Save() g.TranslateTransform(Left() + (Width / 2), Top + (Height / 2)) g.RotateTransform(TailRotation) g.DrawPath(thickPen, tail) g.Restore(gstate) End If gstate = 1000.Save() grand.TranslateTransform(Left, Top) g.FillPath(fillBrush, Path) If BorderVisible Then g.DrawPath(borderPen, Path) Finish If g.Restore(gstate) If TailVisible Then gstate = g.Save() g.TranslateTransform(Left() + (Width / 2), Summit + (Tiptop / two)) chiliad.RotateTransform(TailRotation) grand.FillPath(fillBrush, tail) 1000.Restore(gstate) End If
Once that'due south all washed, at that place's only one matter left to do; draw the text:
sf.LineAlignment = StringAlignment.Middle sf.Alignment = StringAlignment.Heart g.DrawString(Text, Font, textBrush, Premises, sf)
Using the Code
The sample application I've provided makes using the lawmaking very easy equally it volition generate the VB.NET code needed to reproduce the speech balloon you visually design with information technology.
To rapidly apply the code in your project, follow these steps:
- Copy SpeechBalloon.vb from the sample application into your awarding.
- Run the sample application.
- Fiddle with the settings until you have the balloon that y'all want.
- Under the "File" bill of fare, select "Generate Code...". The VB.NET code required to reproduce that balloon volition be displayed below it.
- Copy the generated code from the sample awarding and paste it into your application.
- At some betoken in your awarding, call the
Draw
method on the instance of the speech balloon, passing information technology the appropriateGraphics
object.
Super Happy Bonus
I've built the demo application so that information technology tin as well export the speech balloon you lot pattern to a Portable Network Graphics (PNG) file. Savour!
I made an attempt to comment the demo application code (all in Form1.vb in the sample code), so if you're interested to see how I wrote the demo app, feel free to await through it.
Possible Enhancements
While I think my fiddling speech balloon generator is bang-up, it does have its shortcomings. Here are a listing of possible features that I think would be neat enhancements:
- The generator could utilize a double-buffer to reduce the flickering when redrawing the balloon. I didn't want to complicate the sample lawmaking with that.
- Support for rich text in the airship.
-
Support for rectangular balloons (commonly used in comics to show electronic or not-human communication).- See History Beneath - Ability to have fancy tails (curved, lightning-bolt shaped, little puffs of clouds for idea balloons, etc.).
- Ability to have random-sized bubbling to give a less uniform appearance for starbursts and idea balloons.
- Ability to have the balloon describe its own semi-transparent (i.e., alpha-blended) driblet shadow.
- Ability to accept several balloons continued by small bridging lines (used in comics to separate pieces of a conversation in i panel).
History
- 2010/01/09 - Initial version
- 2010/11/xiv - Added support for rectangular (and round-rectangular) balloons, with adjustable corner radius
Source: https://www.codeproject.com/Articles/51377/Creating-a-Speech-Balloon-Speech-Bubble-in-GDI
Posted by: kendallmouldither1967.blogspot.com
0 Response to "How To Draw A Speech Bubble"
Post a Comment