使用HTML5画布创建页面翻转效果

  • 所需知识:JavaScript,HTML,CSS
  • 要求:文本编辑器,任何支持HTML5 Canvas元素的浏览器
  • 项目时间:3小时
  • 支持文件

长期以来,Web开发人员倾向于使用插件为用户带来真正身临其境且丰富的交互式体验。 HTML5已经开始通过将这些Web扩充的一些最重要的构建块带到开放Web来改变这一切。

我们在Fi.com与谷歌Chrome团队合作,在一个名为HTML5的教育网络应用程序上我学到的关于浏览器和Web的20件事。这个项目背后的一个关键思想是,它最好在一本书的背景下呈现。由于本书的内容非常关注开放式网络技术,因此我们认为通过使容器本身成为这些技术使我们今天能够实现的目标的一个例子来保持这一点非常重要。

我们认为,实现真实世界书籍感觉的最佳方式是模拟模拟阅读体验的优点,同时在导航等领域利用数字领域的优势。在阅读流程的图形和交互式处理方面付出了很多努力 - 尤其是书籍页面如何从一个页面翻转到另一个页面。

本教程将引导您完成使用canvas元素和大量JavaScript创建自己的页面翻转效果的过程。一些基本代码(例如变量声明和事件侦听器订阅)已被排除在本文的片段之外,因此请记住参考教程文件以获取完整代码。

01.标记

重要的是要记住,我们在画布上绘制的内容无法被搜索引擎索引,由访问者选择或通过浏览器内搜索找到。出于这个原因,我们将使用的内容直接放在DOM中,然后由JavaScript操作(如果可用)。这需要的标记是最小的:

复制代码







...

我们有一本书的主要容器元素,它又包含我们书中的不同页面以及我们将绘制翻页的画布元素。在section元素里面有一个内容的div包装器 - 我们需要它能够改变页面的宽度而不影响其内容的布局。

Div具有固定的宽度,并且该部分设置为隐藏其溢出。这导致该部分的宽度充当div的水平掩模。

02.剧本

为页面翻转提供动力所需的代码并不是非常复杂,但它非常广泛,因为它涉及大量程序生成的图形。

让我们首先看一下我们将在整个代码中使用的常量值的描述。

Var BOOK_WIDTH = 830;
Var BOOK_HEIGHT = 260;
Var PAGE_WIDTH = 400;
Var PAGE_HEIGHT = 250;
var PAGE_Y =(BOOK_HEIGHT - PAGE_HEIGHT)/ 2;
Var CANVAS_PADDING = 60;

CANVAS_PADDING在画布周围添加,以便我们可以在翻转时将纸张延伸到书本之外。请注意,此处定义的某些常量也是在CSS中设置的,因此如果要更改书的大小,还需要更新其中的值。

The constant values used throughout the code to track interaction and draw the page flip

整个代码中使用的常量值用于跟踪交互并绘制页面翻转

接下来,我们需要为每个页面定义一个翻转对象。当我们与书籍互动时,这些将不断更新,以反映翻书中当前的进展水平。

var book = document.getElementById(“book”);
var pages = book.getElementsByTagName(“section”);
for(var i = 0,len = pages.length; i <len; i ++){
pages [i] .style.zIndex = len - i;
flips.push({progress:1,target:1,page:pages [i],dragging:false});
}

首先,我们需要通过组织section元素的z-index来确保页面正确分层,以便第一页位于顶部,最后一页位于底部。翻转对象最重要的属性是进度和目标值。这些用于确定页面当前应折叠的距离:-1表示一直到左边,0表示书的死点,+1表示书的最右边。

The progress and target values of the flips are used to determine where the folding page should be drawn on a -1 to +1 scale

翻转的进度和目标值用于确定折叠页面应在-1到+1刻度上绘制的位置

现在我们已经为每个页面定义了一个翻转对象,我们需要开始捕获并使用用户的输入来更新翻转的状态。

Function MouseMoveHandler(event){
//偏移鼠标位置,使脊柱顶部为0,0
mouse.x = event.clientX - book.offsetLeft - (BOOK_WIDTH / 2);
mouse.y = event.clientY - book.offsetTop;
}
Function MouseDownHandler(event){
if(Math.abs(mouse.x)<PAGE_WIDTH){
if(mouse.x <0 && page - 1> = 0){
翻转[page - 1] .dragging = true;
} else if(mouse.x> 0 && page + 1 <flips.length){
翻转[page] .dragging = True;
}
}
//阻止拖动时出现文本选择光标
Event.preventDefault();
}
Function MouseUpHandler(event){
for(var i = 0; i <flips.length; i ++){
If(翻转[i] .dragging){
翻转[i] .target = mouse.x <0? -1:1;
If(翻转[i] .target === 1){
page = page - 1> = 0?第1页:第页;
} Else {
page = page + 1 <flips.length?第+ 1页;页;
}
}
翻转[i] .dragging = False;
}
}

MouseMoveHandler函数更新鼠标对象,以便我们始终朝着最新的光标位置工作。

MouseDownHandler我们首先检查是否在左侧或右侧页面上按下鼠标,以便我们知道我们想要朝哪个方向开始翻转。我们还确保在该方向上存在另一个页面,因为我们可能位于第一页或最后一页。如果在这些检查之后有可用的有效翻转选项,我们将相应翻转对象的拖动标志设置为真正

一旦我们达到了MouseUpHandler我们浏览所有翻转并检查是否有任何标记为拖动,现在应该被释放。当释放一个翻转时,我们将其目标值设置为与它应该翻转的一侧相匹配,具体取决于当前的鼠标位置。页码也会更新以反映此导航。

我们要介绍的下一个代码块是在render函数内部,每秒调用60次来更新并绘制所有活动翻转的当前状态。

If(flip.dragging){
flip.target = Math.max(Math.min(mouse.x / PAGE_WIDTH,1), - 1);
}
flip.progress + =(flip.target - flip.progress)* 0.2;

如果正在拖动翻盖,我们更新其目标以匹配鼠标位置,但是在-1到1比例而不是实际像素上。我们还将进度增加一小部分到目标的距离。这将导致翻转的平滑和动画进展,因为它在每一帧上更新。

if(flip.dragging || Math.abs(flip.progress)<0.997){
DrawFlip(翻转);
}

由于我们要遍历每一帧的所有翻转,我们需要确保只重绘那些活动的翻转。

如果翻页不在书籍边缘的非常近的范围内,或者如果它被标记为拖动,则它将被渲染。

现在所有逻辑都已到位,我们需要根据其当前状态绘制翻转的图形表示。现在是时候看看第一部分了DrawFlip(翻转)功能。

//本书中间的折叠强度最强
var strength = 1 - Math.abs(flip.progress);
//折叠纸张的宽度
var foldWidth =(PAGE_WIDTH * 0.5)*(1 - flip.progress);
//折叠纸张的X位置
var foldX = PAGE_WIDTH * flip.progress + foldWidth;
//由于透视,纸张在书的外面多远
Var VerticalOutdent = 20 * Strength;
//左侧和右侧阴影的最大宽度
var paperShadowWidth =(PAGE_WIDTH * 0.5)* Math.max(Math.min(1 - flip.progress,0.5),0);
//通过设置其宽度以匹配foldX来掩盖页面
flip.page.style.width = Math.max(foldX,0)+“px”;

代码的这一部分首先计算一些我们需要以逼真的方式绘制折叠的视觉变量。我们正在绘制的翻转的进度值在这里起着很大的作用,因为这是我们希望页面折叠出现的地方。为了增加页面翻转效果的深度,我们使纸张延伸到书的顶部和底部边缘之外。当翻盖接近书的书脊时,这种效果达到了顶峰。

既然已经设置了所有逻辑,我们只需要使用我们收集的值来绘制翻转。

Context.save();
context.translate(CANVAS_PADDING +(BOOK_WIDTH / 2),PAGE_Y + CANVAS_PADDING);
var foldGradient = context.createLinearGradient(foldX - paperShadowWidth,0,foldX,0);
FoldGradient.addColorStop(0.35,'#fabafa');
FoldGradient.addColorStop(0.73,'#eeeeee');
FoldGradient.addColorStop(0.9,'#fafafa');
foldGradient.addColorStop(1.0,'#e2e2e2');
Context.fillStyle = FoldGradient;
Context.strokeStyle ='rgba(0,0,0,0.06)';
Context.lineWidth = 0.5;
Context.beginPath();
Context.moveTo(foldX,0);
context.lineTo(foldX,PAGE_HEIGHT);
context.quadraticCurveTo(foldX,PAGE_HEIGHT +(verticalOutdent * 2),foldX - foldWidth,PAGE_HEIGHT + verticalOutdent);
context.lineTo(foldX - foldWidth,-verticalOutdent);
context.quadraticCurveTo(foldX,-verticalOutdent * 2,foldX,0);
Context.fill();
Context.stroke();
Context.restore();

画布API平移(X,Y)方法用于偏移坐标系统,以便我们可以绘制页面翻转,脊柱顶部作为0,0位置。请注意,我们还需要保存()Canvas和。的当前转换矩阵恢复()我们完成后的身份矩阵。

FoldGradient是我们将填充折叠纸的形状,以给它逼真的高光和阴影。我们还在纸张绘图周围添加了一条非常细的线条,以便在背景较浅时纸张不会消失。

现在剩下的就是使用我们上面定义的属性绘制折叠纸的形状。我们的纸张的左侧和右侧绘制成直线,顶部和底部侧面是弯曲的,以使折叠纸张的弯曲感觉穿过。

而已!您现在已经有了一个功能齐全的页面翻页导航。下载文件时,您可能会注意到代码的绘图部分在JavaScript文件中有一些额外的位:这些是作为进一步图形增强添加的阴影。

03.走得更远

这只是利用诸如canvas元素之类的HTML5功能可以实现的一个例子。

我建议你看一下这种技术摘录的更精致的书籍体验,我学到的关于浏览器和网络的20件事:在Www.20thingsilearned.com

The soft page flip in this tutorial becomes even more powerful when paired with other book-like features such as an interactive hard cover

当与其他类似书籍的功能(例如交互式硬封面)配对时,软页面翻转变得更加强大

在那里,您将看到页面翻转如何应用于实际应用程序以及与其他HTML5功能配对时的强大程度。

这篇文章首次出现在.net杂志- 面向网页设计师和开发者的全球畅销杂志。

哈基姆是一名网络开发人员和创意程序员,热衷于将动画和交互作为技术实现。他的工作经验包括各种各样的项目,如活动网站,大型门户网站,实验性HTML5 / CSS3 / JS项目以及使用Adobe AIR的桌面应用程序。在推特上关注哈基姆。

喜欢这个?阅读这些!



翻译字数超限