Leaves is a simple page flip control developed by tow brow. It skillfully integrates the image layer, shadow layer (for translucent pages), and gradient layer (for shadows) to achieve the paging Effect of books. The page turning effect is shown in:
Features
Leaves supports:
Any objects that can be rendered to the graphics context, such as text, images, and PDF
Flip the page by dragging or clicking
Display area of iPad and iPhone size supported
Levels currently does not support the following features
Interaction elements on the page
Light Scan
Class and Interface
Leaves has three main categories: levelsview, levelsviewcontroller, and levelscache:
Levelscache: A helper class used to cache display pages. It caches the displayed content as an image and saves it.
Levelsview: it is a page flip view, and the main effect of page flip is implemented. It defines a series of layer objects and achieves various effects on pages by operating on these layer objects.
Levelsviewcontroller: controller of levelsview
Similar to uitableview, levelsview also has a related data source class (leaveviewdatasource) and delegate class (leavesviewdelegate). They have two methods respectively, as shown below:
CopyCode
@ Protocol leavesviewdatasource <nsobject>
-(Nsuinteger) numberofpagesinleavesview :( leavesview *) leavesview;
-(Void) renderpageatindex :( nsuinteger) index incontext :( cgcontextref) CTX;
@ End
@ Protocol leavesviewdelegate <nsobject>
@ Optional
-(Void) leavesview :( leavesview *) leavesview willturntopageatindex :( nsuinteger) pageindex;
-(Void) leavesview :( leavesview *) leavesview didturntopageatindex :( nsuinteger) pageindex;
@ End
Layer Tree Structure
Shows the layer tree structure in levelsview:
Each layer has its own special purpose, as a display layer of content, or as a shadow layer. The details are as follows:
Toppage layer: displays the content of the current page.
Toppageoverlay layer: During the page turning process, this layer covers the toppage layer, and the color is dark, so that the parts not flipped by toppage become darker and have a shadow effect.
Toppageshadow layer: During page turning, this layer is used to express the shadow formed by the flipped part of toppage.
Toppagereverse layer: During the page turning process, the toppage is flipped to the opposite container layer of the part.
Toppagereverseimage layer: content page on the opposite side. In the vertical screen, the content of the flipped part of the toppage is displayed. The content is mapped to this layer, which makes the book transparent. On the horizontal screen, the content of the next page is displayed.
Toppagereverseoverlay layer: This layer is used to overwrite the toppagereverse layer. The effect is similar to that of toppageoverlay.
Toppagereverseshading layer: This layer forms a shadow on the Right of toppagereverse layer.
Bottompage layer: the layer of the next page of The toppage page.
Bottompageshadow layer: This layer is a shadow layer formed on the left of bottompage during page turning.
Leftpage layer: This layer is the layer of the left-side page in Landscape mode.
Leftpageoverlay layer: This layer covers the leftpage layer. The effect is similar to that of toppageoverlay.
From the above we can see that the layers in the layer tree are mainly divided into three types:
Content display layer: toppage, toppagereverseimage, bottompage, leftpage
Shadow layer: toppageshadow, toppagereverseshading, and bottompageshadow
Cover Layer: toppageoverlay, toppagereverseoverlay, leftpageoverlay
Image Cache
Tow brow adopts the same method when processing different content (text, images, PDF. It caches the content as an image and displays it on the screen. The basic method is to write the content into cgcontextref, and then create an image based on the information in cgcontextref. The specific method is as follows:
Copy code
-(Cgimageref) imageforpageindex :( nsuinteger) pageindex {
Cgcolorspaceref colorspace = cgcolorspacecreatedevicergb (); cgcontextref context = cgbitmapcontextcreate (null,
Pagesize. Width,
Pagesize. height,
8,/* bits per component */
Pagesize. Width * 4,/* bytes per row */
Colorspace,
Kcgimagealphapremultipliedlast | kcgbitmapbyteorder32big );
Cgcolorspacerelstrap (colorspace );
Cgcontextcliptorect (context, cgrectmake (0, 0, pagesize. Width, pagesize. Height ));
[Datasource renderpageatindex: pageindex incontext: Context];
Cgimageref image = cgbitmapcontextcreateimage (context );
Cgcontextrelease (context );
[Uiimage imagewithcgimage: Image];
Cgimagerelease (image );
Return image;
}
Of courseProgramThe content of all pages is not cached. Instead, the appropriate amount of content is cached based on different landscape screens. The cached content will be reorganized every time you flip the page.
Page flip animation implementation
In leaves, the basic principle of page turning is actually very simple: During the page turning process, the frame of each layer in the layer tree structure is constantly adjusted based on the finger movement. After the page turning, re-adjust the content displayed on the content display layer.
To this end, levelsview sets a leafedge variable, which is the percentage position of touch point on the X axis of the screen when the finger moves on the screen. This operation is completed in touchesmoved: withevent:
Copy code
-(Void) touchesmoved :( nsset *) touches withevent :( uievent *) event {
......
Uitouch * Touch = [event. alltouches anyobject];
Cgpoint touchpoint = [Touch locationinview: Self];
[Catransaction begin];
[Catransaction setvalue: [nsnumber numberwithfloat: 0.07]
Forkey: kcatransactionanimationduration];
Self. leafedge = touchpoint. X/self. bounds. Size. width;
[Catransaction commit];
}
In the Set Method of leafedge, we reset the frame attribute of each layer based on the value of leafedge.
Copy code
-(Void) setlayerframes {
Cgrect rightpageboundsrect = self. layer. bounds;
Cgrect lefthalf, righthalf;
Cgrectdivide (rightpageboundsrect, & lefthalf, & righthalf, cgrectgetwidth (rightpageboundsrect)/2.0f, cgrectminxedge );
If (self. mode = leavesviewmodefacingpages ){
Rightpageboundsrect = righthalf;
}
Toppage. Frame = cgrectmake (rightpageboundsrect. Origin. X,
Rightpageboundsrect. Origin. y,
Leafedge * rightpageboundsrect. Size. Width,
Rightpageboundsrect. Size. Height );
Toppagereverse. Frame = cgrectmake (rightpageboundsrect. Origin. x + (2 * leafEdge-1) * rightpageboundsrect. Size. Width,
Rightpageboundsrect. Origin. y,
(1-leafedge) * rightpageboundsrect. Size. Width,
Rightpageboundsrect. Size. Height );
......
}
The last step is how to handle the page turning result when the finger leaves the screen (turning the current page over or not over ). This operation is completed in touchesended: withevent.
Copy code
-(Void) touchesended :( nsset *) touches withevent :( uievent *) event {
......
Uitouch * Touch = [event. alltouches anyobject];
Cgpoint touchpoint = [Touch locationinview: Self];
Bool dragged = distance (touchpoint, touchbeganpoint)> [self dragthreshold];
[Catransaction begin];
Float duration;
If (dragged & self. leafedge <0.5) | (! Dragged & [self touchednextpage]) {
[Self willturntopageatindex: currentpageindex + numberofvisiblepages];
Self. leafedge = 0;
Duration = leafedge;
......
}
Else {
[Self willturntopageatindex: currentpageindex];
Self. leafedge = 1.0;
Duration = 1-leafedge;
.......
}
[Catransaction setvalue: [nsnumber numberwithfloat: Duration]
Forkey: kcatransactionanimationduration];
[Catransaction commit];
}
If you need to perform some operations after turning pages (such as displaying the current page number on the screen), you can implement the leavesview: didturntopageatindex method in the Controller inherited from levelsviewcontroller.
Note that the toppagereverseimage is transformed as follows during portrait.
Copy code
Toppagereverseimage. contentsgravity = kcagravityright;
Toppagereverseimage. Transform = catransform3dmakescale (-1, 1, 1 );
In this way, the content displayed by toppagereverseimage makes people feel that the content of toppage is displayed through paper.
Landscape and Landscape
Leaves also features that it can view two pages of content simultaneously when supporting landscape screens (this effect was improved by Ole begann ). The most important aspect of this improvement is to add the leftpage layer, split the screen into two parts During Horizontal display, and display the leftpage on the left. During the page turning process, toppagereverseimage displays the next page of The toppage page. When you flip the screen, the display of the content is adjusted accordingly.
Reference: App Store-safe page curl animations
Source code: https://github.com/brow/leaves