切割翻页效果(一)

前段时间根据朋友的一个提议做了个翻页动画。效果跟水果忍者切割相似。如图


切割翻页效果(一)

 

效果过程大致如下:

1)根据手势痕迹将当前图片分割为两部分;

2)将分割后的图片拉开一段距离,并适度放大图片,以模拟向屏幕外弹起效果,同时露出底层图片;

3)错位移动分割后的图片;

 

首先遇到的问题是如何对图片进行分割。我选择采用canvas.clipPath来实现;采用这种方法就要先确定PATH中各个节点的坐标;

起初我尝试利用分割线与图片边的交点,以及图片的顶点来确定Path;

如下图:



切割翻页效果(一)

通过观察,却发现交点可以落在图片任意两条不同的边上,而且落点不同与其构成Path的顶点也不同,情况复杂,于是我果断放弃,另谋他路。一番尝试后,我决定采用以下方式;

设mHW为图片对角线的斜率,mSlope分割线的斜率;;

将切割情况分为,mSlope大于还是小于mHW两种情况进行处理;

先看mSlope大于mHW的情况,如图:

 

切割翻页效果(一)
 
 点mDown 和mUp分别表示手指按下和弹起时的位置,两点所在直线即为分割线。分割线与x=-mWidth,x=2mWidth分别交于mX0 和mXw;显然两点坐标可以轻松得到:

 

private void calcPoints() {
		mSlope = (mDown.y - mUp.y) / (mDown.x - mUp.x);
		mX0.x = -mWidth;
		mX0.y = (-mWidth - mUp.x) * mSlope + mUp.y;
		mXw.x = 2 * mWidth;
		mXw.y = mSlope * (2 * mWidth - mUp.x) + mUp.y;
	}

  这样,被分割的两部分路径就总是可以用图中Part1,Part2 两个三角形确定。

Part1的路径为:

if (Math.abs(mSlope) > mHW) {
			if (mSlope < 0) {
				path.moveTo(-mWidth, mXw.y);
				path.lineTo(mXw.x, mXw.y);
				path.lineTo(mX0.x, mX0.y);
				path.close();
			} else {
				path.moveTo(-mWidth, mXw.y);
				path.lineTo(mX0.x, mX0.y);
				path.lineTo(mXw.x, mXw.y);
				path.close();
			}
		}

 Part2的路径为:

 

 

if (Math.abs(mSlope) > mHW) {
			if (mSlope < 0) {
				path.moveTo(2 * mWidth, mX0.y);
				path.lineTo(mXw.x, mXw.y);
				path.lineTo(mX0.x, mX0.y);
				path.close();
			} else {
				path.moveTo(2 * mWidth, mX0.y);
				path.lineTo(mX0.x, mX0.y);
				path.lineTo(mXw.x, mXw.y);
				path.close();
			}
		} 
 

 

而当切割线斜率小于mSlope时,情况与此相似,就不一一赘述了。

 

 

 

你可能感兴趣的:(效果)