Flex翻书效果

来源:互联网 发布:vscode ripgrep 编辑:程序博客网 时间:2024/04/30 16:14

 

 

最早让我做FLEXBOOK的改进,但是实力有限,实在看不懂FLEXBOOK的源码里那堆乱七八糟的东西,刚看到这篇BLOG有解释基本原理,转过来看看,不过好像是翻译过来的,语言风格很明显,而且明显就是FLash做的嘛!


——概念描述

这个项目的概念是使来到我站点的人有机会用FlashMX设计一本虚拟的书,就象一本真正的书那样,不过它是摆在你的计算机桌面上的。你可以一页一页地阅读。

注意,这个课程是面向那些对ActionScript有所了解以及知道如何在FlashMX中编码的人。如果你只知道如何创建一个球并让它在桌面上滚动,那么请过几个月再来吧。

只是开玩笑啦。基本上在这个课程里只有很少的技术。在这个教程中的所有函数是经常使用的。编码非常容易,你需要知道的只是一些基本的三角知识,比如sine(正弦)、cosec(余弦)、hypotenuse(直角三角形的斜边)。这些对于这个教程来说就足够了。所以,放轻松,好好享受吧。

这是一个正在进行的项目。

如果你有任何问题,请给我e-mail。

让我们开始吧。

 

第一部分——基本计算函数(basic calculation functions)

在这个根脚本(root script)里,我们有两个基本计算函数。你可以把它们直接拷贝到你的舞台(stage)上,因为我们将会一遍遍用到它们。一个是getDist,另一个是getAngle。它们对你来说很简单,是吧?老实说,我都没兴趣解释这样的东西,这些是高中数学课上该学的。

第一个函数是获得两点之间的距离。我们需要知道这两点之间的坐标。

// Get the distance between two points. (得到两点之间的距离)
function getDist(px1, py1, px2, py2){
x = px2 - px1;
y = py2 - py1;

hyp = Math.sqrt(Math.pow(x,2) + Math.pow(y,2));

return hyp; 
}



好了,现在你进展已经不错。我们可以试一下更难点的。——怎么获得两点之间的角度。

// Get the angle between two points. (得到两点之间的角度)
function getAngle(px1, py1, px2, py2){
x = px2 - px1;
y = py2 - py1;

hyp = Math.sqrt(Math.pow(x,2) + Math.pow(y,2));

cos = x / hyp;
rad = Math.acos(cos);
// Ask your math teacher if you don’t understand this one.(如果你看不懂,就去问你的数学老师)

deg = 180/(Math.PI / rad);
// Yes, we do got one angle, rad, by 'Math.acos(cos)', but in radians.(是的,我们通过cos得到了一个角度“rad”,不过是以弧度为单位的)

// Therefore, we need do one more step to transfer it to normal angle we need.(因此,我们需要再进一步把它转换成我们所需要的标准的角度)

if(y <0){deg = -deg;}
else if((y == 0) && (x <0)){deg = 180;}

return deg;
}



我不需要做更多解释了吧?

 

第二部分——舞台(stage)上基本的Movie Clips

在库(library)中创建4个方块符号(symbol)。它们是你书中的不同的页面。如果你喜欢,你可以根据需要重新设计。我只需要提醒你一件事,就是,把参考点放在每个symbol的左下角,我们需要用它们来找到页面的位置。



在这个演示例子里,假定我们的书只有4页。如果你想让你的书页数更多,那就请自己加一些新的check situation函数。要确保页面的大小与书本相符。

把它们拖到你的舞台上,确保它们在不同的层面。

按照这个顺序:第4页,第1页,第2页,第3页。

第3页应该在最上面一层。

确保将这些movie clip如下图所示放置。



第3页的具体位置没什么要紧,因为我们将会把它做动态调整。

2、创建一个符号(symbol)圆,并切割下来(cut)。我们需要在移动鼠标的时候用它来检查不同的位置。

3、创建一个包含一个点的symbol,你可以用任何风格的点,这取决于你。

把“点”这个symbol在舞台上放5次,分别命名为D0,D1,D2,D3和D4。



我需要提醒你的是,不要在movie clip Page1和Page4的区域外放置任何movie clip。

4、我们还会需要一些别的符号(symbol),比如阴影或别的什么,我们可以迟一点再创建它们,别担心。

现在再数一次,你库(library)里的符号(symbol)有:

s_circle, s_dot, s_page1, s_page2, s_page3, s_page4

你舞台(stage)上的符号(symbol)有:

checkcircle, D0, D1, D2, D3, D4, page1, page2, page3, page4

把舞台(stage)上所有的movie clip选中,把它们转换(convert)为一个符号(symbol) s_stage。

把s_stage拖到舞台上,把它命名为movie clip“Stage”。

确保movie clip D0位于movie clip“Stage”的中心。

确保movie clip “Stage”的大小是Page 1 加 Page 4。

这就是为什么当你在转换符号s_stage的时候不要在区域外面放置任何movie clip的原因。

基本上,建立movie clip D0到D4 的目的是为了清楚找到参考点。当我们完成这个教程的时候,你可以把这些movie clip的透明度设置为0。我这里就是这么做的。

我们可以在下面的课程中开始编码了。

 

第三部分——初始化

如下图所示初始化所有变量。



// Set the book's width and height. (设置书的宽和高)
stageW = _root.stage._width;
stageH = _root.stage._height; 

// Set reference points' position (设置参考点的位置)
pax=_root.stage.d0._x - stageW/2;
pay=_root.stage.d0._y - stageH/2;

pbx=_root.stage.d0._x - stageW/2;
pby=_root.stage.d0._y + stageH/2;

pcx=_root.stage.d0._x;
pcy=_root.stage.d0._y - stageH/2;

pdx=_root.stage.d0._x;
pdy=_root.stage.d0._y + stageH/2;

pex=_root.stage.d0._x + stageW/2;
pey=_root.stage.d0._y - stageH/2;

pfx=_root.stage.d0._x + stageW/2;
pfy=_root.stage.d0._y + stageH/2;

_root.stage.page3._alpha = 0;
// We need show movie clip Page2 at the beginning, so hide Page3 first.(我们需要在开始的时候显示movie clip Page2,所以先隐藏Page 3)

把这部分代码放入你的第一个根脚本(root frame script)。

——怎么找到第一个点?

第一个点,D1,是你鼠标的位置。(说实在话,在D1的位置上有几种情况。假设你的鼠标离开了movie clip圆,会发生什么?你可以迟一些时候再完成这部分。我已经做好了。这是留给你的作业。)

在给D1的位置赋值之前,我们首先需要一个主函数。

// The main function. (主函数)
function startSlip(){

getD1(); // This function is the one what we need discuss in this course. (这个函数是我们要在这一课中讨论的)

getD234();
DrewMask(); // We will add these two functions later. (我们将在以后添加这两个函数)
}

现在你可以检查如何设置D1了。

// Get the first point, D1's position. (得到第一点,D1的位置)
function getD1(){
if (_root.stage.checkcircle.hittest(_xmouse, _ymouse, true)) {

_root.stage.d1._x = _root.stage._xmouse;
_root.stage.d1._y = _root.stage._ymouse;

}else{
// Finish this part yourself. Basically, I have 3 more functions to set the D1's position. (自己完成这部分。基本上,我还要用三个函数来设置 D1的位置)
}
}

提示:你的鼠标要去四个区域,在每个区域里,D1的位置是不同的。在这个例子里,我们只讨论区域A。我会把所有的代码放在最终文件里,你如果感兴趣的话,可以稍后查看。

因为要按住鼠标拖动页面,你需要移动的第一个点是在页面右下角的点。

很好,我们还有三个点要做,耐心一点。


第四部分——得到所有其他三个点:

同上面一样,你有几种情况要考虑。

第一种情况比较简单。第3点位于边EF上。在这种情况下,点D4与点D3位于同一位置。



另一种情况比较难一点。点D3位于边CE上。你需要计算D3和D4。



或者:



这里,我们需要一些三角函数来获得所有的数值。嗨,一定有更有效的方式来编码,我真是没兴趣再做一遍。:(

我只需要提醒你一件事:

Flash的坐标系开始于左上角,逐渐向下扩展到右边。

对于一个数学家来说,求得所有的点很可能只需要几分钟,但是我却花了整整一个上午。如果你想做,你可以自己做,或者只需拷贝这些代码。

// Using point D1 and Point F find all the other points. (用D1和F来找到其他的点)
function getD234(){

len = _root._root.getDist(pfx, pfy, _root.stage.d1._x, _root.stage.d1._y);
len1 = len/2;
len2 = (pfx - _root.stage.d1._x)/2;

_root.stage.d2._x = pfx - len1*len1/len2;
_root.stage.d2._y = pfy;

len2 = (pfy - _root.stage.d1._y)/2;
len3 = len1*len1/len2;

_root.stage.d3._x = pfx;
_root.stage.d3._y = pfy - len3;

// Check out weather point D4 is at the same location of point D3. (检查D4是否和D3在同一个位置)
if (_root.stage.d3._y < pey){
ptx = pex - (pfx - _root.stage.d2._x)*(pey - _root.stage.d3._y)/len3;
pty = pey;

len = _root.getDist(_root.stage.d3._x, _root.stage.d3._y, ptx, pty);
len1 = (pex - ptx)*(pey - _root.stage.d3._y)/len;

len2 = len1*len1/(pex - ptx);
_root.stage.d4._x = pex - len2*2;

len2 = len1*len1/(pey - _root.stage.d3._y);
_root.stage.d4._y = pey - len2*2;

_root.stage.d3._x = ptx;
_root.stage.d3._y = pty;

}else{
_root.stage.d4._x = _root.stage.d3._x;
_root.stage.d4._y = _root.stage.d3._y;
}
}



哇,现在我们快完成了,继续!


第五部分:——绘制mask shape

你只需要知道两个特别的点。一个点创建一个空的movie clip,并在其中绘制一些东西。另一个点用另一个动画来遮住一个movie clip。

好了,让我们来编码。

// Create masking movie clip (创建遮罩movie clip)
function drawMask(){

_root.stage.createEmptyMovieClip ("triangle", 1); 
with (_root.stage.triangle) {
colors = [ 0xEFEFEF, 0xFFFFFF ];
alphas = [ 100, 100 ];
ratios = [ 0, 0xFF ];
matrix = { a:200, b:0, c:0, d:0, e:200, f:0, g:200, h:200, i:1 };

beginGradientFill( "linear", colors, alphas, ratios, matrix );

moveTo (_root.stage.d1._x, _root.stage.d1._y);
lineTo (_root.stage.d2._x, _root.stage.d2._y);
lineTo (_root.stage.d3._x, _root.stage.d3._y);
lineTo (_root.stage.d4._x, _root.stage.d4._y);
lineTo (_root.stage.d1._x, _root.stage.d1._y);

endFill();
// I don't think I need explain this part. You can find them in the help or reference of Flash MX. I copied them from there. J(我认为不需要解释这部分。你能在Flash MX的帮助或者参考中找到它们。我是从那里拷贝过来的。)

// Pretty clear, right? (很清楚了吧?)
}

setPage3();
// We need move and rotate movie clip Page3 with your mouse move. That is why we need this function here.(我们需要在鼠标移动时移动和旋转movie clip Page3。这就是为什么在这里我们需要这个函数) 

_root.stage.page3.setMask(_root.stage.triangle);

}

这是我们还需要知道的一个函数:setMask。

就个人而言,我认为这个setMask函数在使用时有些小bug。它不象其他函数那么好用。

我要提醒你的另一件事是,在同一级脚本里你只能用setMask一次,意思就是,如果你想同时setMask movie clip Page2,你需要创建新的 mask movie clip,并在不同级的脚本中setMask。

很难理解吗?好吧,在我的例子里,我把下一个setMask放在movie clip Page2里。

// Move and rotate movie clip Page3 (移动并旋转movie clip Page3)
function setPage3(){

_root.stage.page3._x = _root.stage.d1._x;
_root.stage.page3._y = _root.stage.d1._y;

angle = _root.getAngle(_root.stage.stage.d1._x, _root.stage.stage.d1._y, _root.stage.stage.d4._x, _root.stage.stage.d4._y);
_root.stage.page3._rotation = angle + 90;
//Why add 90 degree here? I don't know. I just found that the numbers worked perfectly only by adding that in there. (为什么这里加了90度?我不知道。我只是发现加了这个之后数字才能很好地工作)

_root.stage.page3._alpha = 100;
// Remember we initialize movie clip Page3's alpha as 0? Now we need switch it back. Because movie clip Page2 is on the under level of Page3. (记得我们把movie clip Page3的透明度设置为0了吗?现在我们需要把它变回去。因为movie clip Page2在Page3的下一层。)
}

在这一课程中多加一条编码。

在movie clip “Stage”中:

onClipEvent (enterFrame) {
_root.startSlip();
}

这一段代码使Flash一直检查鼠标的位置。

第六部分:

——在Page2中绘制mask shape

在movie clip Page2里创建一个新的名为Page2_content的movie clip。

随便你取什么名都可以。

把下面的代码加到新的movie clip Page2_content中。

基本上,就象我们在上一个课程中讨论的那样,在同一级的script中,你只能使用setMask一次。这就是为什么在movie clip Page2里还需要再用一次的原因。

这些代码是为了显示底部的movie clip Page4。

// Inside movie clip Page2_content. (在movie clip Page2_content内部)
onClipEvent (enterFrame) {

_parent.createEmptyMovieClip ("triangle2", 1);
_root.stage.page2.page2_content.setMask (_parent.triangle2);

with (_parent.triangle2) {

colors = [ 0xEFEFEF, 0xFFFFFF ];
alphas = [ 0, 0 ];
ratios = [ 0, 0xFF ];
matrix = { a:200, b:0, c:0, d:0, e:200, f:0, g:200, h:200, i:1 };
beginGradientFill( "linear", colors, alphas, ratios, matrix );

moveTo (_root.pdx , _root.pdy - _root.stageH/2);
lineTo (_root.stage.d2._x, _root.stage.d2._y - _root.stageH/2);
lineTo (_root.stage.d3._x, _root.stage.d3._y - _root.stageH/2);
lineTo (_root.pex, _root.pey - _root.stageH/2);
lineTo (_root.pcx, _root.pcy - _root.stageH/2);
lineTo (_root.pdx, _root.pdy - _root.stageH/2);

endFill();
}
}

检查一下你现在进展如何了?很酷,对吧?


总结:——你需要添加的其他东西

现在,我们已经完成得差不多了。但是,当然,我们还需要再做一点什么,使它看起来象一本真正的书。

我们需要加一些阴影movie clip。我用png文件来做透明效果。并且保证它随着Page3一起移动旋转。那些代码有些相似。角度有些不同,因为现在旋转轴不再是边D1、D4,而是边D2、D3。

另外:你要添加一个函数来检测页面如何回退和前进。在我最终的版本里,我用了mouse release函数。

基本上,还会有比较难的一步,就是如何查验第一页和最后一页。如果没有那些,你就不能增加页数。

现在我又累又饿,剩下的事情就作为你们自己的作业吧。:)

祝好运


 

原创粉丝点击