`
caibinghong
  • 浏览: 143293 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

HTML5开发的翻页效果

 
阅读更多

http://www.html5china.com/course/20111012_2244.html

 

HTML5开发的翻页效果

简介 2010年F-i.com和Google Chrome团队合力致力于主题为《20 Things I Learned about Browsers and theWeb》( www.20thingsilearned.com )的web app的宣传教育。这个项目最主要的思想是在传达,用web展现电子书的…

简介
2010年F-i.com和Google Chrome团队合力致力于主题为《20 Things I Learned about Browsers and the Web》(www.20thingsilearned.com)的web app的宣传教育。这个项目最主要的思想是在传达,用web展现电子书的内容是最合适的选择。因为展现电子书的内容是前所未有的web技术,我们坚信以现在的技术完全可以用一个容器来展现这样的例子。



书籍的封面同时也是《20 Things I Learned About Browsers and the Web》的主页(www.20thingsilearned.com)
我们认为,要实现阅读真正书籍的感觉最好的方法是模仿书籍的阅读体验,同时充分利用电子媒介的优势如导航。我在书籍的视觉和交互效果上面下了很大的功夫,特别是翻页的效果。


开始制作
本教程会带领里学习HTML5电子书的制作流程,并教你用canvas元素和JavaScript来制作自己的电子书。关于JavaScript的基础代码,如变量声明和事件侦听等不在本教程的范围内,具体请参考实例源代码。
开始之前,我们还是先看一下demo的效果吧,这样我们可以有目的行的去学习。

电子书结构
你一定要时时记住,在canvas里绘制的所有信息都无法被搜索引擎搜到,也无法由用户在浏览器中搜索到。由于这个原因,我们在DOM中显示文本内容,然后由JavaScript来操控它。所以电子书的结构非常简单:

XML/HTML Code复制内容到剪贴板
  1. <div id="book">  
  2.   <canvas id="pageflip-canvas"></canvas>  
  3.   <div id="pages">  
  4.     <section>  
  5.       <div> <!-- Any type of contents here --> </div>  
  6.     </section>  
  7.     <!-- More <section>'s here -->  
  8.   </div>  
  9. </div>  
电子书的结构中包含一个主容器,它包含所有的页面和用来绘制翻页效果的canvas元素。在section元素中包含一个div元素,它包含了电子书页面的内容,我们可以调整这个div的宽度而不影响页面内容的布局。div有固定的宽度,同时section设置溢出隐藏,这样section元素的作用实际是作为div的水平方向的遮罩。

打开电子书,可以看到一个背景图片,它包含纸张的材质和书籍效果。
逻辑
实现翻页效果的代码并不是很复杂,但代码量很大,因为有很多图形效果需要用代码实现。首先我们从代码中的常量开始说起,它的使用贯穿整个程序。

JavaScript Code复制内容到剪贴板
  1. var BOOK_WIDTH = 830;  
  2. var BOOK_HEIGHT = 260;  
  3. var PAGE_WIDTH = 400;  
  4. var PAGE_HEIGHT = 250;  
  5. var PAGE_Y = ( BOOK_HEIGHT - PAGE_HEIGHT ) / 2;  
  6. var CANVAS_PADDING = 60;  
CANVAS_PADDING是canvas周围的留白,这样在翻页的时候页面可以超出书的尺寸。要注意的是,这里设置的常量有的也在CSS中设置了这些值,所以如果你想修改书的尺寸,同样需要修改CSS中相应的值。
 


贯穿代码中的常量,用来跟踪鼠标交互并绘制翻页页面
下一步需要为每个页面定义一个flip对象,在翻页交互过程中,它会持续更新来反应当前翻页的状态。

JavaScript Code复制内容到剪贴板
  1. // Create a reference to the book container element  
  2. var book = document.getElementById( "book" );  
  3.   
  4. // Grab a list of all section elements (pages) within the book  
  5. var pages = book.getElementsByTagName( "section" );  
  6.   
  7. forvar i = 0, len = pages.length; i < len; i++ ) {  
  8.     pages[i].style.zIndex = len - i;  
  9.   
  10.     flips.push( {  
  11.     progress: 1,  
  12.     target: 1,  
  13.     page: pages[i],  
  14.     dragging: false  
  15.   });  
  16. }  
首先我们要保证section元素的z-index被有序的排列,这样页面才可以正确的排序,也就是说第一页在上面,最后一页在最下面。flip对象最重要的属性是progress和target值。它们用来定义翻动页面折叠的大小,-1表示整页翻到左边,0表示翻到书的中间位置,+1表示整页翻到书的最右边。
 



Progress和target值用来定义页面的折叠量,可以是-1到+1之间的值.
现在每个页面都有自己的flip对象了,下面我们学获取用户的鼠标位置,并根据这个值开始翻页。

JavaScript Code复制内容到剪贴板
  1. function mouseMoveHandler( event ) {  
  2.   // Offset mouse position so that the top of the book spine is 0,0  
  3.   mouse.x = event.clientX - book.offsetLeft - ( BOOK_WIDTH / 2 );  
  4.   mouse.y = event.clientY - book.offsetTop;  
  5. }  
  6.   
  7. function mouseDownHandler( event ) {  
  8.   // Make sure the mouse pointer is inside of the book  
  9.   if (Math.abs(mouse.x) < PAGE_WIDTH) {  
  10.     if (mouse.x < 0 && page - 1 >= 0) {  
  11.       // We are on the left side, drag the previous page  
  12.       flips[page - 1].dragging = true;  
  13.     }  
  14.     else if (mouse.x > 0 && page + 1 < flips.length) {  
  15.       // We are on the right side, drag the current page  
  16.       flips[page].dragging = true;  
  17.     }  
  18.   }  
  19.   
  20.   // Prevents the text selection  
  21.   event.preventDefault();  
  22. }  
  23.   
  24. function mouseUpHandler( event ) {  
  25.   forvar i = 0; i < flips.length; i++ ) {  
  26.     // If this flip was being dragged, animate to its destination  
  27.     if( flips[i].dragging ) {  
  28.       // Figure out which page we should navigate to  
  29.       if( mouse.x < 0 ) {  
  30.         flips[i].target = -1;  
  31.         page = Math.min( page + 1, flips.length );  
  32.       }  
  33.       else {  
  34.         flips[i].target = 1;  
  35.         page = Math.max( page - 1, 0 );  
  36.       }  
  37.     }  
  38.   
  39.     flips[i].dragging = false;  
  40.   }  
  41. }  
mouseMoveHandler方法会实时更新mouse对象的内容,这样我们可以得到鼠标的精确位置。

在mouseDonwHandler中,检测鼠标是在书的左边还是右边按下,记得得知翻页的方向。我还需要知道翻页方向的下一张是否还有页面,因为我们会遇到第一页或最后一页的情况。如果所有的flip选项都有检测没有问题,设置该flip对象的dragging属性为true。
在mouseUpHandler中,我们会检测每个页面是否被拖动,如果是则释放该页面的拖动。停止拖动后,页面会根据鼠标的位置决定是向前翻动还是向后翻动。同时页面的页面也会被更新,作为页面的导航。
渲染
现在大部分的逻辑运算都已经完成了,下面我们要学习如果在canvas元素中渲染折叠的页面。这些渲染的效果大部分都在render()方法中完成,这个方法每秒钟会执行60次,来实时更新翻动页面的状态。

JavaScript Code复制内容到剪贴板
  1. function render() {  
  2.   // Reset all pixels in the canvas  
  3.   context.clearRect( 0, 0, canvas.width, canvas.height );  
  4.   
  5.   forvar i = 0, len = flips.length; i < len; i++ ) {  
  6.     var flip = flips[i];  
  7.   
  8.     if( flip.dragging ) {  
  9.       flip.target = Math.max( Math.min( mouse.x / PAGE_WIDTH, 1 ), -1 );  
  10.     }  
  11.   
  12.     // Ease progress towards the target value  
  13.     flip.progress += ( flip.target - flip.progress ) * 0.2;  
  14.   
  15.     // If the flip is being dragged or is somewhere in the middle  
  16.     // of the book, render it  
  17.     if( flip.dragging || Math.abs( flip.progress ) < 0.997 ) {  
  18.       drawFlip( flip );  
  19.     }  
  20.   
  21.   }  
  22. }  
开始渲染之前,用clearRect(x,y,w,h)方法重置canvas。重置整个canvas画布会大大降低运行的性能,相比之下,仅仅重置需要重新绘制的部分,效率会更高。但是为了不偏离本教程的话题,我们还是重置更个canvas画布

如果页面正在拖动,那么他的target值设置为鼠标坐标相对于电子书宽度的位置,而不是实际的像素值。同时progress也会一点点增加至target值,这样翻动每帧都会更新,也就得到了我们看到的页面平滑的翻动动画效果。
因为每一帧都要遍历所有的页面,所以我们需要保证只重绘当前活动的页面。如果页面翻动没有很接近书的边缘(BOOK_WIDTH的0.3%),或者页面的flagged属性值是dragging,我们认为该页面是当前活动的页面。
现在所有的逻辑运算都已经完成了,下面需要根据页面的当前状态绘制翻动页面效果。我们来看胰腺癌drawFlip()方法的第一部分。

JavaScript Code复制内容到剪贴板
  1. // Determines the strength of the fold/bend on a 0-1 range  
  2. var strength = 1 - Math.abs( flip.progress );  
  3.   
  4. // Width of the folded paper  
  5. var foldWidth = ( PAGE_WIDTH * 0.5 ) * ( 1 - flip.progress );  
  6.   
  7. // X position of the folded paper  
  8. var foldX = PAGE_WIDTH * flip.progress + foldWidth;  
  9.   
  10. // How far outside of the book the paper is bent due to perspective  
  11. var verticalOutdent = 20 * strength;  
  12.   
  13. // The maximum widths of the three shadows used  
  14. var paperShadowWidth = (PAGE_WIDTH*0.5) * Math.max(Math.min(1 - flip.progress, 0.5), 0);  
  15. var rightShadowWidth = (PAGE_WIDTH*0.5) * Math.max(Math.min(strength, 0.5), 0);  
  16. var leftShadowWidth = (PAGE_WIDTH*0.5) * Math.max(Math.min(strength, 0.5), 0);  
  17.   
  18. // Mask the page by setting its width to match the foldX  
  19. flip.page.style.width = Math.max(foldX, 0) + "px";  
这部分的代码开始是一些变量的计算,它们用来绘制真实的页面翻动效果。Progress变量在这些变量中扮演最重要的角色,因为它是页面要翻动到的位置。为了添加深度效果,我们让页面可以超出书的边界,当页面翻动至书脊位置时,超出部分达到了极限。
 

页面翻动时的折叠效果.
现在所有的值都一个就位,万事俱备,只差绘制页面了!

JavaScript Code复制内容到剪贴板
  1. context.save();  
  2. context.translate( CANVAS_PADDING + ( BOOK_WIDTH / 2 ), PAGE_Y + CANVAS_PADDING );  
  3.   
  4. // Draw a sharp shadow on the left side of the page  
  5. context.strokeStyle = 'rgba(0,0,0,'+(0.05 * strength)+')';  
  6. context.lineWidth = 30 * strength;  
  7. context.beginPath();  
  8. context.moveTo(foldX - foldWidth, -verticalOutdent * 0.5);  
  9. context.lineTo(foldX - foldWidth, PAGE_HEIGHT + (verticalOutdent * 0.5));  
  10. context.stroke();  
  11.   
  12. // Right side drop shadow  
  13. var rightShadowGradient = context.createLinearGradient(foldX, 0,  
  14.               foldX + rightShadowWidth, 0);  
  15. rightShadowGradient.addColorStop(0, 'rgba(0,0,0,'+(strength*0.2)+')');  
  16. rightShadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.0)');  
  17.   
  18. context.fillStyle = rightShadowGradient;  
  19. context.beginPath();  
  20. context.moveTo(foldX, 0);  
  21. context.lineTo(foldX + rightShadowWidth, 0);  
  22. context.lineTo(foldX + rightShadowWidth, PAGE_HEIGHT);  
  23. context.lineTo(foldX, PAGE_HEIGHT);  
  24. context.fill();  
  25.   
  26. // Left side drop shadow  
  27. var leftShadowGradient = context.createLinearGradient(  
  28.     foldX - foldWidth - leftShadowWidth, 0, foldX - foldWidth, 0);  
  29. leftShadowGradient.addColorStop(0, 'rgba(0,0,0,0.0)');  
  30. leftShadowGradient.addColorStop(1, 'rgba(0,0,0,'+(strength*0.15)+')');  
  31.   
  32. context.fillStyle = leftShadowGradient;  
  33. context.beginPath();  
  34. context.moveTo(foldX - foldWidth - leftShadowWidth, 0);  
  35. context.lineTo(foldX - foldWidth, 0);  
  36. context.lineTo(foldX - foldWidth, PAGE_HEIGHT);  
  37. context.lineTo(foldX - foldWidth - leftShadowWidth, PAGE_HEIGHT);  
  38. context.fill();  
  39.   
  40. // Gradient applied to the folded paper (highlights & shadows)  
  41. var foldGradient = context.createLinearGradient(  
  42.     foldX - paperShadowWidth, 0, foldX, 0);  
  43. foldGradient.addColorStop(0.35, '#fafafa');  
  44. foldGradient.addColorStop(0.73, '#eeeeee');  
  45. foldGradient.addColorStop(0.9, '#fafafa');  
  46. foldGradient.addColorStop(1.0, '#e2e2e2');  
  47.   
  48. context.fillStyle = foldGradient;  
  49. context.strokeStyle = 'rgba(0,0,0,0.06)';  
  50. context.lineWidth = 0.5;  
  51.   
  52. // Draw the folded piece of paper  
  53. context.beginPath();  
  54. context.moveTo(foldX, 0);  
  55. context.lineTo(foldX, PAGE_HEIGHT);  
  56. context.quadraticCurveTo(foldX, PAGE_HEIGHT + (verticalOutdent * 2),  
  57.                          foldX - foldWidth, PAGE_HEIGHT + verticalOutdent);  
  58. context.lineTo(foldX - foldWidth, -verticalOutdent);  
  59. context.quadraticCurveTo(foldX, -verticalOutdent * 2, foldX, 0);  
  60.   
  61. context.fill();  
  62. context.stroke();  
  63.   
  64. context.restore();  
在canvas的API中tranlate(x,y)方法用来移动画布的坐标系统,以便于我们可以以书脊的顶端作为(0,0)原点来绘制翻动的页面。注意,我们需要使用save()方法保存当前canvas的变换,变换完成后调用restore()方法。
 


绘制翻动页面的起始点,同translate(x,y)方法,将其从canvas的左上角移动到书脊顶端,这样简化了绘制的逻辑
foldGradient方法用来填充折叠的页面,同时绘制真实的高光和阴影效果。同时我还为页面绘制了一条很窄的黑边,防止在较亮的背景下页面“消失”。
现在剩下的就是用我们前面定义的变量绘制折叠的页面。页面左右两侧用直线绘制,顶部和底部绘制弯曲的曲线,产生一种纸张折叠的感觉。页面的折叠程度由verticalOutdent值决定。
全文结束!现在你得到的是一个完整的HTML5电子书。


翻书实例Demo
翻页效果是为了像用户传递正确的翻页体验,所有本教程中的图片无法让你感受到效果,点击下面的链接体验一下最终的结果。

查看实例

下载源码 (75k .zip)

分享到:
评论

相关推荐

    HTML5翻页特效(日历)

    一款使用jQuery++制作的翻页特效示例,适用于制作像小册子(如日历、电子书等)这类应用的翻页浏览功能场景。  感兴趣的开发者可以下载源码,解压后导入MM开发环境进行修改优化,可跨平台导出apk(Android)和ipa...

    html6game book 动态响应式翻页效果.rar

    html6game 设计开发的 book 动态翻页效果,使用了jQuery框架,建议在Chrome、火狐浏览器和IE9浏览器下使用 功能特点: 支持ie9 ,html5浏览器。 单页和双页。 自动播放和暂停。 点击左右翻页。 鼠标点击左右页面...

    Android仿苹果的上下翻页效果

    效果不错,能够上下翻页,有兴趣童鞋可以学习学习,据说是失传已久的江湖秘笈,哈哈~~建议开发童鞋使用跨平台开发工具——统一开发环境UDE来进行查看、调试、开发哦~~统一开发环境是一款HTML5跨平台一站式应用开发、...

    HTML5实现3D翻页电子书特效.zip

    HTML5实现3D翻页电子书特效是一款适用于手机端的3D翻页效果电子书特效。

    移动端H5开发 Turn.js实现很棒的翻书效果

    主要为大家详细介绍了Turn.js实现很棒的翻书效果,对Turn.js翻书效果的实现进行总结,感兴趣的小伙伴们可以参考一下

    HTML5电子书翻页动画特效

    HTML5电子书翻页动画特效源代码

    JSP 实现网页翻页

    本功能是以读书管理为例子而实现的翻页功能,目的希望大家很够很容易掌握它,同时将它学会。希望能给大家带来方便! Web应用开发的JavaServer Pages技术方法 在开发JSP规范的过程中,太阳微系统公司(Sun ...

    Android仿苹果上下翻页效果源代码

    统一开发环境是一款HTML5跨平台一站式应用开发、调试和部署工具, 它支持HTML5跨平台开发,原有Java跨平台插件支持Android、Symbian、Kjava的跨平台和原生开发,已覆盖Android、iOS、WP、Symbian、Kjava操作系统平台...

    HTML5开源好例子

    包括多种css3, javascript和html5(包括canvas)等多种效果例子:进度条,下拉框,登陆,翻页,搜索,钟表,日期插件,相册,侧框,宣传栏,立体旋转,鼠标效果,按钮,放大镜,音量控制,动态墙,视频等等50多种...

    Android项目源码本站发布的第5个动画源码集.rar

    Android项目源码本站发布的第5个动画源码集项目是一个安卓动画app,包括字体闪烁、抽屉式拖动、listview上拉刷新、翻页效果、二维码扫描、3d图片旋转、通讯录、fragment的滑动添加、android对HTML5的加载、view的...

    Cocos2D-X游戏开发技术精解

    4.9.2 翻页动作(CCPageTurn3D) 130 4.9.3 波纹动作(CCWaves3D) 130 4.9.4 格子动作类(CCGridAction) 131 4.10 动画动作类 132 4.10.1 精灵帧 133 4.10.2 精灵帧缓冲 134 4.10.3 动画类 135 4.10.4 动画动作 ...

    H5微场景源码.zip

    伦敦时装周开发制作(001) 财富·雪山和院html5响应式(002) 翻书式手机场景应用(003) 故宫手机场景应用(004) 婚礼请柬手机场景应用(005) 2014中国自媒体年会场景应用(007) 择居网人才招聘手机场景应用(008) 卡片式...

    android动画源码集

    自己积累和整理的一个安卓动画app,包括字体闪烁、抽屉式拖动、listview上拉刷新、翻页效果、二维码扫描、3d图片旋转、通讯录、fragment的滑动添加、android对HTML5的加载、view的开门动画、镜头由远及近的效果、...

    PHP程序开发范例宝典III

    实例125 应用HTML标记进行跳转 186 实例126 使用脚本语言实现页面跳转 187 5.3 包含文件 189 实例127 include()函数的应用 189 实例128 include_once()函数的应用 190 实例129 require()函数的应用 191 ...

    ios-上下无限滑动列表.zip

    最近看到iPhone上的日历上下无线滚动效果很炫,就尝试自己实现。 在网上看到这个StreetScroller(https://developer.apple.com/library/ios/samplecode/StreetScroller/Introduction/Intro.html) 就拿他改了一下,...

    Android项目源码本站发布的第5个动画源码集

    Android项目源码本站发布的第5个动画源码集项目是一个安卓动画app,包括字体闪烁、抽屉式拖动、listview上拉刷新、翻页效果、二维码扫描、3d图片旋转、通讯录、fragment的滑动添加、android对HTML5的加载、view的...

Global site tag (gtag.js) - Google Analytics