11.
12.varflip=flips;
13.
14.
15.
16.if(flip.dragging){
17.
18.flip.target=Math.max(Math.min(mouse.x/PAGE_WIDTH,1),-1);
19.
20.}
21.
22.
23.
24.//Easeprogresstowardsthetargetvalue
25.
26.flip.progress+=(flip.target-flip.progress)*0.2;
27.
28.
29.
30.//Iftheflipisbeingdraggedorissomewhereinthemiddle
31.
32.//ofthebook,renderit
33.
34.if(flip.dragging||Math.abs(flip.progress)<0.997){
35.
36.drawFlip(flip);
37.
38.}
39.
40.
41.
42.}
43.
44.}
复制代码
开始渲染之前,用clearRect(x,y,w,h)方法重置canvas。
重置整个canvas画布会大大降低运行的性能,相比之下,仅仅重置需要重新绘制的部分,效率会更高。
但是为了不偏离本教程的话题,我们还是重置更个canvas画布。
如果页面正在拖动,那么他的target值设置为鼠标坐标相对于电子书宽度的位置,而不是实际的像素值。
同时progress也会一点点增加至target值,这样翻动每帧都会更新,也就得到了我们看到的页面平滑的翻动动画效果。
因为每一帧都要遍历所有的页面,所以我们需要保证只重绘当前活动的页面。
如果页面翻动没有很接近书的边缘(BOOK_WIDTH的0.3%),或者页面的flagged属性值是dragging,我们认为该页面是当前活动的页面。
现在所有的逻辑运算都已经完成了,下面需要根据页面的当前状态绘制翻动页面效果。
我们来看胰腺癌drawFlip()方法的第一部分。
1.//Determinesthestrengthofthefold/bendona0-1range
2.
3.
4.varstrength=1-Math.abs(flip.progress);
5.
6.
7.
8.//Widthofthefoldedpaper
9.
10.varfoldWidth=(PAGE_WIDTH*0.5)*(1-flip.progress);
11.
12.
13.
14.//Xpositionofthefoldedpaper
15.
16.varfoldX=PAGE_WIDTH*flip.progress+foldWidth;
17.
18.
19.
20.//Howfaroutsideofthebookthepaperisbentduetoperspective
21.
22.varverticalOutdent=20*strength;
23.
24.
25.
26.//Themaximumwidthsofthethreeshadowsused
27.
28.varpaperShadowWidth=(PAGE_WIDTH*0.5)*Math.max(Math.min(1-flip.progress,0.5),0);
29.
30.varrightShadowWidth=(PAGE_WIDTH*0.5)*Math.max(Math.min(strength,0.5),0);
31.
32.varleftShadowWidth=(PAGE_WIDTH*0.5)*Math.max(Math.min(strength,0.5),0);
33.
34.
35.
36.//MaskthepagebysettingitswidthtomatchthefoldX
37.
38.flip.page.style.width=Math.max(foldX,0)+"px";
复制代码
这部分的代码开始是一些变量的计算,它们用来绘制真实的页面翻动效果。
Progress变量在这些变量中扮演最重要的角色,因为它是页面要翻动到的位置。
为了添加深度效果,我们让页面可以超出书的边界,当页面翻动至书脊位置时,超出部分达到了极限。
页面翻动时的折叠效果.
现在所有的值都一个就位,万事俱备,只差绘制页面了!
1.context.save();
2.
3.
4.context.translate(CANVAS_PADDING+(BOOK_WIDTH/2),PAGE_Y+CANVAS_PADDING);
5.
6.
7.
8.//Drawasharpshadowontheleftsideofthepage
9.
10.context.strokeStyle='rgba(0,0,0,'+(0.05*strength)+')';
11.
12.context.lineWidth=30*strength;
13.
14.context.beginPath();
15.
16.context.moveTo(foldX-foldWidth,-verticalOutdent*0.5);
17.
18.context.lineTo(foldX-foldWidth,PAGE_HEIGHT+(verticalOutdent*0.5));
19.
20.context.stroke();
21.
22.
23.
24.//Rightsidedropshadow
25.
26.varrightShadowGradient=context.createLinearGradient(foldX,0,
27.
28.foldX+rightShadowWidth,0);
29.
30.rightShadowGradient.addColorStop(0,'rgba(0,0,0,'+(strength*0.2)+')');
31.
32.rightShadowGradient.addColorStop(0.8,'rgba(0,0,0,0.0)');
33.
34.
35.
36.context.fillStyle=rightShadowGradient;
37.
38.context.beginPath();
39.
40.context.moveTo(foldX,0);
41.
42.context.lineTo(foldX+rightShadowWidth,0);
43.
44.context.lineTo(foldX+rightShadowWidth,PAGE_HEIGHT);
45.
46.context.lineTo(foldX,PAGE_HEIGHT);
47.
48.context.fill();
49.
50.
51.
52.//Leftsidedropshadow
53.
54.varleftShadowGradient=context.createLinearGradient(
55.
56.foldX-foldWidth-leftShadowWidth,0,foldX-foldWidth,0);
57.
58.leftShadowGradient.addColorStop(0,'rgba(0,0,0,0.0)');
59.
60.leftShadowGradient.addColorStop(1,'rgba(0,0,0,'+(strength*0.15)+')');
61.
62.
63.
64.context.fillStyle=leftShadowGradient;
65.
66.context.beginPath();
67.
68.context.moveTo(foldX-foldWidth-leftShadowWidth,0);
69.
70.context.lineTo(foldX-foldWidth,0);
71.
72.context.lineTo(foldX-foldWidth,PAGE_HEIGHT);
73.
74.context.lineTo(foldX-foldWidth-leftShadowWidth,PAGE_HEIGHT);
75.
76.context.fill();
77.
78.
79.
80.//Gradientappliedtothefoldedpaper(highlights&shadows)
81.
82.varfoldGradient=context.createLinearGradient(
83.
84.foldX-paperShadowWidth,0,foldX,0);
85.
86.foldGradient.addColorStop(0.35,'#fafafa');
87.
88.foldGradient.addColorStop(0.73,'#eeeeee');
89.
90.foldGradient.addColorStop(0.9,'#fafafa');
91.
92.foldGradient.addColorStop(1.0,'#e2e2e2');
93.
94.
95.
96.context.fillStyle=foldGradient;
97.
98.context.strokeStyle='rgba(0,0,0,0.06)';
99.
100.context.lineWidth=0.5;
101.
102.
103.
104.//Drawthefoldedpieceofpaper
105.
106.context.beginPath();
107.
108.context.moveTo(foldX,0);
109.
110.context.lineTo(foldX,PAGE_HEIGHT);
111.
112.context.quadraticCurveTo(foldX,PAGE_HEIGHT+(verticalOutdent*2),
113.
114.foldX-foldWidth,PAGE_HEIGHT+verticalOutdent);
115.
116.context.lineTo(foldX-foldWidth,-verticalOutdent);
117.
118.context.quadraticCurveTo(foldX,-verticalOutdent*2,foldX,0);
119.
120.
121.
122.context.fill();
123.
124.context.stroke();
125.
126.
127.
128.context.restore();
复制代码
在canvas的API中tranlate(x,y)方法用来移动画布的坐标系统,以便于我们可以以书脊的顶端作为(0,0)原点来绘制翻动的页面。
注意,我们需要使用save()方法保存当前canvas的变换,变换完成后调用restore()方法。
绘制翻动页面的起始点,同translate(x,y)方法,将其从canvas的左上角移动到书脊顶端,这样简化了绘制的逻辑
foldGradient方法用来填充折叠的页面,同时绘制真实的高光和阴影效果。
同时我还为页面绘制了一条很窄的黑边,防止在较亮的背景下页面“消失”。
现在剩下的就是用我们前面定义的变量绘制折叠的页面。
页面左右两侧用直线绘制,顶部和底部绘制弯曲的曲线,产生一种纸张折叠的感觉。
页面的折叠程度由verticalOutdent值决定。
全文结束!
现在你得到的是一个完整的HTML5电子书。
翻书实例Demo
翻页效果是为了像用户传递正确的翻页体验,所有本教程中的图片无法让你感受到效果,点击下面的链接体验一下最终的结果。
下一步
如果本教程中的电子书加上一个硬书皮,会使它在翻页的基础上,给人带来更好的阅读体验
展开阅读全文
相关搜索