android翻书效果实现原理( 贝塞尔曲线绘制原理/点坐标计算)
fmms
13年前
<p>实现真实的翻页效果,为了能在翻页的过程中看到下一页的内容,在翻页之前必须准备两张页面,一张是当前页,另一张是下一页。翻页的过程就是对这两张页面的剪切,组合过程。</p> <p>用户看到的可以分为3部分:当前页的可见部分(下图绿色部分),把书页翻起来后看到的背面区域(下图黄色部分),把书页翻起来后看到的下一页的一角(下图绿色部分)。</p> <p><span style="line-height:normal;"><img alt="android翻书效果实现原理( 贝塞尔曲线绘制原理/点坐标计算)" src="https://simg.open-open.com/show/71c161f891a62e635e74114ee8729d41.jpg" width="320" height="219" /></span><br /> </p> <p>假设我们已经求得了包含黄色区域和蓝色区域的Path, 假设为mPath0,那么绿色区域则可以使用</p> <p>Canvas.clipPath(mPath0, Region.Op.XOR)来剪裁绘制;</p> <p>而蓝色区域则可以通过使用(假设黄色区域的Path为mPath1)</p> <p><span style="line-height:normal;"><span style="line-height:normal;">Canvas.clipPath(mPath0); </span></span></p> <p><span style="line-height:normal;">Canvas.clipPath(mPath1, Region.Op.DIFFERENCE); </span><span style="line-height:normal;"><span style="line-height:normal;color:#008200;">//绘制第一次不同于第二次的区域</span></span> </p> <p>下面我们来研究如何求取mPath0:</p> <p>上图黄色和蓝色区域的mPath0,可以通过以下获取:</p> <p><span style="line-height:normal;"><span style="line-height:normal;">mPath0.moveTo(jx, jy); <br /> </span></span></p> <p><span style="line-height:normal;">mPath0.quadTo(hx, hy, kx, ky); </span></p> <p><span style="line-height:normal;">mPath0.lineTo(ax, ay); <br /> </span></p> <p><span style="line-height:normal;">mPath0.lineTo(bx, by); </span></p> <p><span style="line-height:normal;">mPath0.quadTo(ex, ey, cx,cy); </span></p> <p><span style="line-height:normal;">mPath0.lineTo(fx, fy); </span></p> <p><span style="line-height:normal;">mPath0.close(); </span></p> <p>接着就是要求出绘制path0所需的各个顶点。</p> <p><span style="line-height:normal;"><img alt="android翻书效果实现原理( 贝塞尔曲线绘制原理/点坐标计算)" src="https://simg.open-open.com/show/3aaed666aacfa83ef315d5ab5978fe16.jpg" width="320" height="217" /></span><br /> 我们已知的条件是:a点坐标(触摸点),f点坐标(显示界面的大小),直线eh是af的垂直平分线。</p> <p>剩下的就变成数学问题啦~~</p> <p>先来求出g点坐标因为g为af中点:</p> <p>显然gx=(ax+fx)/2; gy=(ay+fy)/2;</p> <p>e点坐标:</p> <p>添加补助线gm,m点坐标为(gx, mHeight);</p> <p>由相似垂直三角形egm和gmf可知:</p> <p>em=gm*gm/mf;</p> <p>这样e点坐标为:(gx-em, mHeight)</p> <p>同理可以求出h点坐标。</p> <p>C点坐标:</p> <p>为简化计算,我们令n点为ag中点,这样有三角形cjf和ehf得:</p> <p>cx=ex- ef/2 ;</p> <p>c点坐标为:(ex- ef/2, mHeight)</p> <p>同理求得j点坐标。</p> <p>以下推导需要较多的数学知识,不记得的童鞋,自觉复习去~~</p> <p>一条直线的函数为:</p> <p>Y=ax+b;</p> <p>通过已知两点求直线: a = (y2-y1)/(x2-x1);</p> <p>b = (x2*y1-y2*x1)/(x2-x1);</p> <p>两条相交直线交点的坐标为:x= (b2-b1)/(a1-a2);</p> <p>y=a1x+b1或者y=a2x+b2</p> <p>综上,4点相交的直线的交点为:</p> <p>x=( (x4*y3-y4*x3)/(x4-x3)-(x2*y1-y2*x1)/(x2-x1)) /</p> <p>((y2-y1)/(x2-x1)- (y4-y3)/(x4-x3) )</p> <p>= ( (x4*y3-y4*x3) (x2-x1)- (x2*y1-y2*x1) (x4-x3) ) /</p> <p>( (y2-y1) (x4-x3)- (y4-y3) (x2-x1) )</p> <p>将之前求得的 a,e,c,j四个点带入上式则可以求出 b. 同理可求k点。</p> <p>d点坐标:</p> <p>d为pe的中点,所以:</p> <p>dx=((cx+bx)/2+ex)/2</p> <p>dy=((cy+by)/2+ey)/2</p> <p>同理 可求 i 点。</p>