最近在看扔物线的 hencoder 自定义 view 系列,有个图标翻页旋转效果很炫酷。自己思考加上看了位大神的思路,总算做出来了。(GIF 录制的有点卡,真实效果可以自己运行查看)
效果
思路
整体由三个属性动画构成。首先把整个图标平均分成两部分,一部分先向上翻折(最开始的动画)称为 a 半边;另一部分最后向上翻折(最后一个动画)称为 b 半边。
第一个动画:使用 camera 3d 动画,将 a 半边沿着 Y 轴反方向旋转 45 度;
第二个动画:使用 canvas 2d 动画旋转,将“a 半边的 3d 效果”逆时针旋转 270 度(就是我们看到的平面旋转效果);
第三个动画:b 半边沿着 Y 轴旋转 45 度。
光是描述有点难形容,若是没搞懂思路,只能通过代码一步一步走,慢慢推倒理解了。核心代码如下:
/**
* a半边的动画旋转角度(第一个动画 3d)
*/
private int degreeY;
/**
* b半边的动画旋转角度(第三个动画 3d)
*/
private int degreeNextY;
/**
* 画布的动画旋转角度(第二个动画 2d)
*/
private int degreeZ;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int x = centerX - bitmap.getWidth() / 2;
int y = centerY - bitmap.getHeight() / 2;
// a半边的处理
canvas.save();
camera.save();
canvas.translate(centerX, centerY);
// 第一个动画的3d旋转
camera.rotateY(degreeY);
// 旋转画布
canvas.rotate(degreeZ);
// 此时图标的正中心跟坐标原点位置相同
canvas.clipRect(0, -centerY, centerX, centerY);
camera.applyToCanvas(canvas);
// 记住画布要旋转回来
canvas.rotate(-degreeZ);
canvas.translate(-centerX, -centerY);
camera.restore();
canvas.drawBitmap(bitmap, x, y, paint);
canvas.restore();
// b半边的处理
canvas.save();
camera.save();
canvas.translate(centerX, centerY);
// b半边也要跟着旋转(保持另外半边不动)
canvas.rotate(degreeZ);
// 第三个动画的 3d 旋转
camera.rotateY(degreeNextY);
// 此时图标的正中心跟坐标原点位置相同
canvas.clipRect(-centerX, -centerY, 0, centerY);
camera.applyToCanvas(canvas);
// 记住画布要旋转回来
canvas.rotate(-degreeZ);
canvas.translate(-centerX, -centerY);
camera.restore();
canvas.drawBitmap(bitmap, x, y, paint);
canvas.restore();
}
详细代码在我的 GitHub上,欢迎大家 star。
网友评论