对sunnyxibei关于Flipboard 红板报的翻页效果的解读

        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        int x = centerX - bitmapWidth / 2;
        int y = centerY - bitmapHeight / 2;

        //画变换的一半
        //先旋转,再裁切,再使用camera执行3D动效,**然后保存camera效果**,最后再旋转回来
        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        canvas.rotate(-degreeZ);
        camera.rotateY(degreeY);
        camera.applyToCanvas(canvas);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.rotate(degreeZ);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);
        canvas.restore();

        //画不变换的另一半
        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        canvas.rotate(-degreeZ);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        canvas.clipRect(-centerX, -centerY, 0, centerY);
        //此时的canvas的坐标系已经旋转,所以这里是rotateY
        camera.rotateY(fixDegreeY);
        camera.applyToCanvas(canvas);
        canvas.rotate(degreeZ);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);
        canvas.restore();

首先,解释下为什么用的是 canvas.clipRect(-centerX, -centerY, 0, centerY);而不是canvas.clipRect(0, -bitmapHeight/2, bitmapWidth/2, bitmapHeight/2);
我们应该意识到clipRect的行为不是真的裁切了图片,而是让图片的一小部分显示在方框里。因此,如果采取了canvas.clipRect(0, -bitmapHeight/2, bitmapWidth/2, bitmapHeight/2);你会发现是这样的效果

image.png

其实是因为剪裁的框框不够大,把边角裁掉了


image.png

需要注意的是canvas的旋转,旋转的不是坐标系。要证明这个很简单,我们在rotate前先裁剪。

        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        //canvas.rotate(-degreeZ);
        camera.rotateY(0);
        camera.applyToCanvas(canvas);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        //canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.rotate(270);
        canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);

        canvas.restore();

效果是这样的


image.png

当我们在rotate后再裁剪

        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        //canvas.rotate(-degreeZ);
        camera.rotateY(0);
        camera.applyToCanvas(canvas);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.rotate(270);
        //canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);

        canvas.restore();
image.png

我们发现这两者有着区别,原因就是rotate旋转的不是坐标系,而是当前的画面。

实现三维旋转(0度)并裁切的效果

        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        canvas.rotate(-degreeZ);
        camera.rotateY(0);
        camera.applyToCanvas(canvas);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.rotate(degreeZ);

        //canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);

        canvas.restore();
GIF2.gif

实现三维的旋转,这里需要注意的是如果把 camera.rotateY(-45);设为0,整个画面看起来时不动的,但其实它在旋转。

        canvas.save();
        camera.save();
        canvas.translate(centerX, centerY);
        canvas.rotate(-degreeZ);
        camera.rotateY(-45);
        camera.applyToCanvas(canvas);
        //计算裁切参数时清注意,此时的canvas的坐标系已经移动
        //canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.rotate(degreeZ);

        //canvas.clipRect(0, -centerY, centerX, centerY);
        canvas.translate(-centerX, -centerY);
        camera.restore();
        canvas.drawBitmap(bitmap, x, y, paint);

        canvas.restore();
GIF3.gif

PS
如果你的图片文件没有建立分辨率文件夹分类放好,就会出现图片过大的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容