灵动的锦鲤鱼
1.绘制小鱼
1-1.技术点
绘制实现主要用到技术:
1. 自定义Drawable动画
2. Android的坐标及角度
3. 正余弦函数的使用以及角度和弧度的转换
1-2.分解图
分析效果:
1. 小鱼的身体各个部件都是简单的半透明几何图形
2. 各个部件都可以活动
3. 从头到尾方向的部件摆动幅度越来越大、频率越来越高
1-3.鱼鳍的绘制
鱼的绘制必须要有个相对点,这样移动这个点,就能移动整个鱼了。下面只讲解鱼鳍的绘制,其他类
似。
先假设鱼身角度为0°,即头朝向X轴正方向。通过重心点以及第一节身长的一半的长度,以及角度即可
计算出头部的圆心坐标,然后再以头部圆心坐标和0.9R的长度,顺时针旋转80°确定右边鱼鳍的坐标
点。
宽高值:4.19R * 2 = 8.38R
1-5.源码
1-5-1.自定义Drawable,重写方法
public class FishDrawable extends Drawable {
/**
* 绘制,类似自定义View中的onDraw方法
*/
@Override
public void draw(@NonNull Canvas canvas) {
makeFish(canvas);
}
/**
* 设置透明度的方法
*/
@Override
public void setAlpha(int alpha) {
// 设置Drawable的透明度,一般情况下将此alpha值设置给Paint
mPaint.setAlpha(alpha);
}
/**
* 设置了一个颜色过滤器,那么在绘制出来之前,被绘制内容的每一个像素都会被颜色过滤器改变
*/
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
// 设置颜色滤镜,一般情况下将此值设置给Paint
mPaint.setColorFilter(colorFilter);
}
1-5-2.初始化
/**
* 这个值,可以根据setAlpha中设置的值进行调整。比如,alpha == 0时设置为
PixelFormat.TRANSPARENT。
* 在alpha == 255时设置为PixelFormat.OPAQUE。在其他时候设置为
PixelFormat.TRANSLUCENT。
* PixelFormat.OPAQUE:便是完全不透明,遮盖在他下面的所有内容
* PixelFormat.TRANSPARENT:透明,完全不显示任何东西
* PixelFormat.TRANSLUCENT:只有绘制的地方才覆盖底下的内容
*/
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
/**
* 在View使用wrap_content的时候,设置固定宽度,默认为-1
*/
@Override
public int getIntrinsicWidth() {
return (int) (8.38f * HEAD_RADIUS);
}
/**
* 在View使用wrap_content的时候,设置固定高度,默认为-1
*/
@Override
public int getIntrinsicHeight() {
return (int) (8.38f * HEAD_RADIUS);
}
}
private Path mPath;
private Paint mPaint;
//转弯更自然的重心(身体的中心点)
private PointF middlePoint;
public FishDrawable() {
init();
}
private void init() {
// 路径
mPath = new Path();
// 画笔
mPaint = new Paint();
// 抗锯齿
mPaint.setAntiAlias(true);
// 画笔类型填充
mPaint.setStyle(Paint.Style.FILL);
// 防抖
mPaint.setDither(true);
// 设置颜色
mPaint.setColor(Color.argb(OTHER_ALPHA, 244, 92, 71));
// 与Point一样,只是坐标为浮点数
1-5-3.计算坐标
sinA = a/c --> sinA * c = a --> 得到B点的y坐标
cosA = b/c --> cosA * c = b --> 得到B点的x坐标
Math.sin()、Math.cos()的参数是弧度。坐标是按数学中的坐标。
Math.toRadians() 将角度转成弧度。
圆是360度,也是2π弧度,即360°=2π
注意点:
与数学坐标不同的是Android的坐标中Y轴正方向是朝下的,但是角度却和平面直角坐标系的计算
方法一样,即原点指向X轴正方向为0°,正角度是逆时针旋转,负角度是顺时针旋转。
那么问题就来了:坐标系不同,角度转动方式却一样,这就导致Math.sin(α)与安卓中的sin值符号
相反。
所以我们需要将Math.sin(α)取反,根据下面的两个公式,我们只需要将α加上或者减去180°即可。
// 重心位于整个控件的中心,保证鱼旋转的空间
middlePoint = new PointF(4.18f * HEAD_RADIUS, 4.18f * HEAD_RADIUS);
}
/**
* 输入起点、长度、旋转角度计算终点
*
* @param startPoint 起点
* @param length 长度
* @param angle 旋转角度
* @return 计算结果点
*/
public static PointF calculatPoint(PointF startPoint, float length, float angle)
{
// Math.toRadians 角度转弧度 --- sin\cos的参数是弧度制
float deltaX = (float) Math.cos(Math.toRadians(angle)) * length;
// 符合Android坐标的y轴朝下的标准
评论0