Click here to Skip to main content
Click here to Skip to main content
Go to top

A Page Turn Effect Using C#

, 24 Feb 2006
Rate this:
Please Sign up or sign in to vote.
This article demonstrates how to use GDI+ to create a page turn effect.

Introduction

Figure 1 - Turn the page animation.

This article presents a method for creating a page turn effect that could be useful when displaying bitmaps side by side as if they are pages in a book or photo album. The page turn effect gives a realistic transition between the simulated pages.

Background

The inspiration for writing this article came from a desire to create a reusable photo album component to display pictures. I chose to use C# and GDI+ to enhance my understanding of graphics programming in the .NET environment.

The technical background for creating this effect came from The Page Turn Effect in Flash MX by Sham Bhangal, author of Flash Hacks. Sham's article uses a line of symmetry to control the visible areas of the pages participating in the animation. There are differences between the Flash MX and the GDI+ approaches; however, the concepts of calculating and then using a line of symmetry to control visible page areas are the same.

Throughout this article, it is assumed that pages 3 and 4 are the current pages and that the animation will show the transition to pages 5 and 6. In other words, the animation will show page 4 being turned.

Animation technique

The following figure illustrates the important areas and variables used throughout the animation:

Figure 2 - Areas and important parameters.

The entire page turn animation can be summarized as:

  1. Draw the current pages 3 and 4 in their entirety. The visible part of page 4 after drawing areas B and C will represent area A.
  2. Calculate the line of symmetry and the clipping regions for areas B and C.
  3. Draw area B. This is the visible portion of the page "under" the page being turned (page 6).
  4. Translate the coordinates to the hot spot, and rotate the coordinates.
  5. Draw area C. This is the visible portion of the "underside" of the page being turned (page 5).

The current pages

The Page Turn Effect in Flash MX article points out that the current pages do not participate in the animation. This means that for each frame of the animation the current pages (3 and 4) are drawn first without clipping or any transformations. The visible areas B and C will be drawn on top of the current pages.

Hot spot

I borrowed the term "hot spot" from The Page Turn Effect in Flash MX article. The hot spot represents the location of the page fold along the horizontal axis, and it is the point where a line of symmetry will start. During the animation, the hot spot always moves from the page edge to the center of the book. The distance from the page edge to the hot spot (x) is increased for each frame of the animation. The animation will stop when the hot spot reaches the center of the book; when x = PAGE_WIDTH.

Line of symmetry

The line of symmetry represents the page fold. It is used to control the visible portion of the pages participating in the animation. In .NET terms, the line of symmetry controls two things:

  1. The clipping region bounding areas B and C.
  2. The translated coordinate origin for area C.

The line of symmetry can be described by the following equations:

  • a = 45 + ( (45 *x) / PAGE_WIDTH )
  • h = x Tan ( a )

Notice that angle a will increase as the distance x increases. The equation shows that when x = 0 then a = 45 degrees, and when x = PAGE_WIDTH then a = 90 degrees.

When the animation starts, x will be 0. Therefore areas B and C will not be visible. As x increases, the line of symmetry will form the hypotenuse of a triangle. The triangle bounded by the line of symmetry, distance "x", and the calculated height "h" will create a closed path. Figure 2 shows an example of this case.

As x continues to increase, the condition h>=PAGE_HEIGHT will be become true. When this happens, the path under the line of symmetry will be changed from a triangle to a trapezoid. The height of the trapezoid will be bounded by PAGE_HEIGHT. Figure 1 is an example of this case.

The closed path, either triangle or trapezoid, will define the clipping regions for areas B and C. To see this graphics path in action, set the constant INCLUDE_DRAW_GRAPHICS_PATH to true in the provided source code. This will draw a gold outline around the path.

Area A

This is the visible area of the page being turned, page 4, after areas B and C are drawn.

Area B

Area B is from the bitmap representing the page "under" the page being turned. In this example, area B is the visible part of page 6. Area B is simply drawn by setting a clipping region for the animation frame to the closed path under the line of symmetry. The bitmap for this page is then drawn directly over the page being turned. It should be obvious that as x increases (and angle a increases) more of this page will become visible.

To see the relationship of area A to area B, set the constant INCLUDE_UNDERSIDE_PAGE_IN_ANIMATION to false. This simply removes area C from the animation.

Area C

Area C is from the bitmap representing the underside of the page being turned. In this example, area C is the visible part of page 5. Area C is defined by the line of symmetry, but it is on the opposite side of the page. For example, as page 4 is turned, area B will be the lower right portion of page 6 and area C will be the lower left portion of page 5. Figure 3 shows how the graphics paths for area B and area C are related:

Figure 3 - Relationship between areas B and C.

An off screen bitmap, pageUndersideImage, is used when drawing area C. The clip region for the new bitmap is defined by the graphics path under the line of symmetry. The image for page 5 is drawn into this new buffer. This newly created image will be drawn adjacent to area B.

Stitching area C to area B

When the off screen image for area C is ready, it can be drawn onto the current animation frame:

  1. First the coordinate system is translated to the hot spot.
  2. The coordinate system is then rotated by 180-2a degrees. Refer to Figure 4 to see this relationship.
  3. The image holding area C is drawn at the coordinates (-x,-PAGE_HEIGHT). Figure 5 illustrates drawing area C on the rotated coordinate system.

Figure 4 - Rotation angles to match lines of symmetry.

Figure 5 - Rotated coordinate system

I found lining up areas B and C to be challenging because the colors of the current page would bleed through along the line of symmetry (in this case a few red pixels from page 4). The workaround that I implemented include setting a graphic object's PixelOffsetMode to PixelOffsetMode.Half while drawing area B or C:

g.PixelOffsetMode= PixelOffsetMode.Half;

I also found that adding 1 pixel (or subtracting 1 pixel) when translating the coordinates to the hot spot, before drawing area C, also prevents color bleeding:

PathTranslationMatrix.Translate((float)hotSpot.Origin.X+1, 
                                   (float)hotSpot.Origin.Y);

To use the PixelOffsetMode workaround, set the boolean USE_PIXEL_MODE_OFFSET to true in the provided source.

Painting the animation

Each frame of the animation is drawn to an off-screen buffer, CurrentShownBitmap, in the timer1_Tick event handler. The OnPaint event handler simply draws the contents of CurrentShownBitmap to the screen.

Key functional descriptions

Calculation of the graphics paths for area B and area C for each frame of the animation is preformed by the function:

private GraphicsPath GetPageUnderGraphicsPath(int x, 
                   ref double a, int height, int width, 
                   bool isUnderSide, TurnType type)

Parameter x represents the hot spot's distance from the page edge (as discussed above). The height and width parameters indicate the current page's height and width. The isUnderside parameter is used to tell the routine if the graphics path being calculated is for area C (the underside of the page being turned). The last parameter type indicates if the current animation is for a left or right page turn. Essentially, isUnderside and type are used to get the orientation of the graphics path correct. Parameter a represents the current angle a as discussed above. The value for a is returned from this function and later used when rotating the coordinate axis before drawing area C (see figures 4 and 5).

Using the code

Setting up the control

For simplicity, this control contains its own bitmaps. Initialization of the bitmaps occurs in the function LoadSamples(). This function is called in the constructor of the sample form.

Controlling the animation frame rate and count

The frame rate of the animation is controlled by a timer. The public property TickSpeed can be used to control the rate (in millisecond resolution). The number of animation frames is controlled by how far the hot spot is moved during each timer tick. The public property MoveXBy is exposed to control the distance x has moved.

Adjusting the height

Clipping along the top of the underside image (page) is a problem . The public property HeightAdjustment has been introduced to allow a little more room at the top of the control to work around clipping issues.

Starting the animation

This component exposes two methods to start the animation. animateRightPageTurn() and animateLeftPageTurn().

Points of interest

  • I originally tried to solve the non linear equation h = x Tan( 45 + ((45 * (x)) / PAGE_WIDTH) ) for the value of x where h=PAGE_HEIGHT. My brute force attempt at solving this equation is included with the source code for this article. Is there a more elegant solution to this problem?

History

  • 2006-02-25
    • Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bob Hartman
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pinmembersportlife4-Sep-14 3:17 
Generalthanks PinmemberChu Van Dat17-Oct-12 4:12 
GeneralMy vote of 5 PinmemberMember 378450222-Jun-12 0:53 
QuestionHow to add image ? Pinmemberle si nam11-Nov-10 15:17 
GeneralVerticillate page! Pinmembermahboobeh mohamadi10-Oct-10 23:03 
QuestionHow to add a page?? Pinmembergpdiseno8-Jun-10 3:39 
GeneralPageTurnEffectResize&ChangeColorOfImage Pinmembermary_eastland13-Apr-09 7:37 
GeneralC++ Version PinmemberMember 44463519-Jan-09 5:23 
General"Drop shadows" and "Smooth turning" Pinmemberwerter11-Jun-07 21:05 
GeneralQuestion PinmemberShin-Ra31-Mar-07 10:28 
GeneralThanks! Pinmemberemarti31-Mar-07 6:20 
GeneralPage Turn Pinmemberyenkay27-Feb-07 20:15 
GeneralA Page Turn Effect Using OpenGL or GLUT PinmemberYokuta16-Aug-06 5:06 
Questioncan anybody help me out regarding this project....... Pinmemberprashanthmaalay28-Jun-06 21:17 
AnswerRe: can anybody help me out regarding this project....... PinmemberBob Hartman2-Jul-06 1:19 
Generalpage turn on images Pinmemberrrbhaius17-Jun-06 2:00 
Generalpage turn for PDF files Pinmemberrrbhaius31-May-06 20:49 
NewsPage flipping W/VB 2005 Express Pinmemberechris22-May-06 17:17 
GeneralRe: Page flipping W/VB 2005 Express PinmemberBob Hartman2-Jul-06 2:00 
GeneralRe: Page flipping W/VB 2005 Express Pinmemberechris29-Jul-06 14:53 
GeneralWeb Version Pinmembernancyjane7712-Apr-06 9:15 
GeneralPage turn effect Pinmemberechris12-Mar-06 6:44 
General:) amazing PinmemberBnaya Eshet1-Mar-06 10:35 
Generalvery nice but ! PinmemberJavad Roshdi1-Mar-06 2:24 
GeneralRe: very nice but ! PinmemberBob Hartman10-Mar-06 0:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 25 Feb 2006
Article Copyright 2006 by Bob Hartman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid