简介
本文主要实现了类似于折纸翻书的效果。
主要技术点:
- 多边形遮罩
- 节点截图
- 自定义assmbler
Demo引擎版本:2.4.4
效果
分析
一眼看上去图像分为三部分:其中【1】的区域是图中【1】+【2】那么大。
基本思路:
【1】部分使用多边形遮罩,这样的好处是【1】内的spine等动画还可以继续播放,另一个好处是假设第二页在第一页的下面,当第一页使用多边形遮罩后,其实第二页直接就露出来了,这样第二页的所有动画其实都不受影响。先不考虑2的区域如何实现,现在就变成了当手指move时,不断的去计算1的包围盒,并且设置多边形遮罩,使第二页的页面露出来,效果如图:
多边形遮罩主要核心代码:
mask._updateGraphics = function (polygon) {
let node = this.node;
// @ts-ignore
let graphics = mask._graphics;
// Share render data with graphics content
graphics.clear(false);
// @ts-ignore
let width = node._contentSize.width;
// @ts-ignore
let height = node._contentSize.height;
// @ts-ignore
let x = -width * node._anchorPoint.x;
// @ts-ignore
let y = -height * node._anchorPoint.y;
if (!polygon) {
graphics.rect(x, y, width, height);
graphics.close();
graphics.fill();
return;
}
graphics.lineWidth = 10;
graphics.fillColor.fromHEX("#ff0000");
if (polygon.length === 0) polygon.push(cc.v2(0, 0));
graphics.moveTo(polygon[0].x, polygon[0].y);
for (let i = 1; i < polygon.length; i++) {
graphics.lineTo(polygon[i].x, polygon[i].y);
}
graphics.lineTo(polygon[0].x, polygon[0].y);
graphics.fill();
};
【2】部分使用的是自定义assmbler,这部分东西需要多多理解。群里大佬有过一些详细的讲解,我贴几个链接。
官方文档
https://docs.cocos.com/creator/manual/zh/advanced-topics/custom-render.html
思路:假设我们已经拿到了2区域的位置坐标,如何将下一页的纹理显示到这个区域里面?
- 获取下一页的截图。
- 将截图纹理进行自定义渲染。
第一步很好做到,重点是第二步。
在说第二步之前还是得回归到前面的一个问题,就是我们已经假设拿到了所有的区域坐标,这部分坐标是如何获取到的?贴一个@白玉无冰大佬的教程:
大佬的文章里有如何获取到手指划过时得到两个区域的方法。注:上述链接中的代码是3.0引擎的,很多api和2.x区别还是很大滴,主要是理解数学计算的过程。
借鉴(白嫖)到大佬的分割代码之后,我们可以得到两个关键的东西splitPolygons和splitUvs
splitPolygons是两个区域的分割坐标组成的数组,splitUvs是两个区域的分割的纹理坐标组成的数组。
如果我们将前面截图获取到的纹理的顶点坐标设置成splitPolygon,将其纹理坐标设置成splitUv,并且设置了正确的索引数组,那么得到的就是一个看起来被调整了角度的只有部分显示的图片。效果如图:
这时可以发现,宇智波鼬变得有点可怕呢。。。
出现这个情况的原因是我们的uv取得是漏出来区域的部分的坐标,需要轴对称一下采样当前纹理相对于y轴对称的另一面的纹理。。方法就是 1-当前纹理坐标.x。
这样效果就OK了。
真的ok了吗?
完善
1.给翻页的缝隙加一点阴影。没啥技术含量,就是算坐标然后贴一个黑乎乎的九宫格图片上去,调整一下透明度就ok了。
2.翻到中轴线自动切页:更没啥技术含量,翻到一半自动翻过去。。。体验稍微好一点,要不然可能会出现从底下往上翻的情况。。
关于自定义assmbler的知识,没接触过的需要一点点时间去梳理,上面大佬们和官方的文章已经讲解的很好了,这里就不再赘述了。
总结:
- 当前页面用多边形遮罩
- 当点击屏幕时根据坐标判断是【下一页】的操作还是【上一页】的操作,然后调整下层页面的zindex,使漏出来的页面是对应的上下页。
- 此时把预先截好的图拿出来作为纹理,通过自定义assmbler渲染出来即可。
其实整体思路和@白玉无冰大佬的折纸很像。
引擎方面试了2.3.2和2.4.4都可以运行。。
工程内是个简单的demo,而且可能会有一些小bug,不过正常使用应该没问题。如果用于生产,资源管理那些需要自己去处理。
参考链接