风车控件, 光圈控件
https://www.cnblogs.com/willhua/p/5763189.html
参考大神的思路, 动手改造加深理解
要点
- 定义扇叶 (30, 60, 90 的直角三角形)
- 找到内六边形顶点
- 依次移动到顶点,进行旋转(参考第4幅图, 半透明是移动前的图形, 理解下面的计算)
mPoints[0].x = curRadius / 2;
mPoints[0].y = -curRadius * COS_30;
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.huawei.camera.canvas.MyTextView android:layout_width="100dp" android:layout_height="400dp" /> </LinearLayout>
代码参考:
package com.huawei.camera.canvas; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.PorterDuff; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; public class MyTextView extends View { private static final String TAG = "MyTextView"; private static final float ROTATE_ANGLE = 30; private static final int BACKGROUND_COLOR_ACTIVE = Color.parseColor("#FFFFFFFF"); private static final float COS_30 = 0.866025f; private static final float MIN_RADIUS = 17.5f/COS_30; private static final float MAX_RADIUS = 67f/COS_30; private static final int SPACE = 3; private static final int BLADE_COLOR = Color.parseColor("#FF00FF00"); private static final int VIRTUAL_BLADE_COLOR = Color.parseColor("#3300FF00"); private int mCircleRadius; private int mWidth; private PointF[] mPoints = new PointF[6]; private Bitmap mBlade; private Bitmap mVirtualBlade; private Bitmap mBmp; private Canvas mBmpCanvas; private Path mPath; private Paint mPaint; private int k = 0; public MyTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } class AnimationRotateRunnable implements Runnable { @Override public void run() { invalidate(); } } @Override protected void onDraw(Canvas canvas) { Log.i(TAG, "onDraw: " + getHeight()); mBmpCanvas = canvas; mBmpCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//清理画布, 防止透明背景出现叠加 mBmpCanvas.drawColor(BACKGROUND_COLOR_ACTIVE); mBmpCanvas.save(); calculatePoints(0); mBmpCanvas.translate(mWidth / 2, mWidth / 2); mBmpCanvas.rotate(k % 360); //mBmpCanvas.clipPath(mPath); for (int i = 0; i < 6; i++) { mBmpCanvas.save(); mBmpCanvas.translate(mPoints[i].x, mPoints[i].y); mBmpCanvas.rotate(-i * 60); mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint); mBmpCanvas.restore(); } //postInvalidateDelayed(20); mBmpCanvas.restore(); mBmpCanvas.drawLine(0f, mWidth, mWidth, mWidth, mPaint); //2nd mBmpCanvas.save(); calculatePoints(0.3f); mBmpCanvas.translate(mWidth / 2, 3 * mWidth / 2); //mBmpCanvas.clipPath(mPath); for (int i = 0; i < 6; i++) { mBmpCanvas.save(); mBmpCanvas.translate(mPoints[i].x, mPoints[i].y); mBmpCanvas.rotate(-i * 60); mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint); mBmpCanvas.restore(); } mBmpCanvas.restore(); mBmpCanvas.drawLine(0f, 2*mWidth, mWidth, 2*mWidth, mPaint); //3rd mBmpCanvas.save(); calculatePoints(0.6f); mBmpCanvas.translate(mWidth / 2, 5 * mWidth / 2); //mBmpCanvas.clipPath(mPath); for (int i = 0; i < 6; i++) { mBmpCanvas.save(); mBmpCanvas.translate(mPoints[i].x, mPoints[i].y); mBmpCanvas.rotate(-i * 60); mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint); mBmpCanvas.restore(); } mBmpCanvas.restore(); mBmpCanvas.drawLine(0f, 3*mWidth, mWidth, 3*mWidth, mPaint); //4th mBmpCanvas.save(); calculatePoints(0.9f); mBmpCanvas.translate(mWidth / 2, 7 * mWidth / 2); //mBmpCanvas.clipPath(mPath); mBmpCanvas.drawBitmap(mVirtualBlade, 0, 0, mPaint); for (int i = 0; i < 6; i++) { mBmpCanvas.save(); mBmpCanvas.translate(mPoints[i].x, mPoints[i].y); mBmpCanvas.rotate(-i * 60); mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint); mBmpCanvas.restore(); } mBmpCanvas.restore(); k += 1; } private void calculatePoints(float progress) { if (mCircleRadius - SPACE <= 0) { Log.e(TAG, "the size of view is too small and Space is too large"); return; } float curRadius = MIN_RADIUS + progress * (MAX_RADIUS - MIN_RADIUS); mPoints[0].x = curRadius / 2; mPoints[0].y = -curRadius * COS_30; mPoints[1].x = -mPoints[0].x; mPoints[1].y = mPoints[0].y; mPoints[2].x = -curRadius; mPoints[2].y = 0; mPoints[3].x = mPoints[1].x; mPoints[3].y = -mPoints[1].y; mPoints[4].x = -mPoints[3].x; mPoints[4].y = mPoints[3].y; mPoints[5].x = curRadius; mPoints[5].y = 0; } private void init() { mWidth = 350; mCircleRadius = 80; mBmp = Bitmap.createBitmap(mWidth, mWidth, Bitmap.Config.ARGB_8888); mBmpCanvas = new Canvas(mBmp); mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); mPaint.setAntiAlias(true); for (int i = 0; i < 6; i++) { mPoints[i] = new PointF(); } mPath = new Path(); mPath.addCircle(0, 0, mCircleRadius, Path.Direction.CW); createBlade(); createVirtualBlade(); } private void createBlade() { mBlade = Bitmap.createBitmap(mCircleRadius, (int) (mCircleRadius * 2 * COS_30), Bitmap.Config.ARGB_8888); Path path = new Path(); Canvas canvas = new Canvas(mBlade); path.moveTo(SPACE / 2 / COS_30, SPACE); path.lineTo(mBlade.getWidth(), mBlade.getHeight()); path.lineTo(mBlade.getWidth(), SPACE); path.close(); canvas.clipPath(path); canvas.drawColor(BLADE_COLOR); } private void createVirtualBlade() { mVirtualBlade = Bitmap.createBitmap(mCircleRadius, (int) (mCircleRadius * 2 * COS_30), Bitmap.Config.ARGB_8888); Path path = new Path(); Canvas canvas = new Canvas(mVirtualBlade); path.moveTo(SPACE / 2 / COS_30, SPACE); path.lineTo(mVirtualBlade.getWidth(), mVirtualBlade.getHeight()); path.lineTo(mVirtualBlade.getWidth(), SPACE); path.close(); canvas.clipPath(path); canvas.drawColor(VIRTUAL_BLADE_COLOR); } }
变成光圈控件:
只需要对canvas执行clipPath