Canvas模擬太陽地球月球的運動過程

先看效果圖

這裏寫圖片描述

代碼

package com.test.paintdemo.pathrelate;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.view.View;

import com.test.paintdemo.R;

/**
 * Created by ygdx_lk on 17/6/23.
 */

public class PlanetCircle extends View {

    private  Paint mPaintCircle, mPaintSun, mPaintOne, mPaintTwo;
    private final Bitmap mBitmap;
    private float fraction_earth;
    private float fraction_moon;
    private static final String TAG = "PlanetCircle";
    private int mViewWidth, mViewHeight;


    public PlanetCircle(Context context) {
        super(context);
        //軌道畫筆
        mPaintCircle = new Paint();
        mPaintCircle.setStyle(Paint.Style.STROKE);
        mPaintCircle.setColor(Color.GRAY);
        mPaintCircle.setStrokeWidth(3);
        mPaintCircle.setAntiAlias(true);

        //太陽
        mPaintSun = new Paint();
        mPaintSun.setColor(Color.RED);
        mPaintSun.setStyle(Paint.Style.FILL);
        mPaintSun.setAntiAlias(true);

        //地球
        mPaintOne = new Paint();
        mPaintOne.setAntiAlias(true);
        //月亮
        mPaintTwo = new Paint();
        mPaintTwo.setAntiAlias(true);

        //圖片
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 12;       // 縮放圖片
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.arrow, options);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        //畫布平移
        canvas.translate(mViewWidth / 2, mViewHeight / 2);

        //1.畫軌道
        Path path = drawPlanetPathWayOval(canvas, - getWidth() / 3, - getWidth() / 4, getWidth() / 3, getWidth() / 4);

        //2.畫太陽
        drawSun(canvas);

        //繪製圖片
        drawBitmap(canvas, path, fraction_earth);

        //3.畫地球及月球
        drawPlanetEarth(canvas, path);

        //4.轉動
        startAnim();
    }

    /**
     * 啓動動畫
     */
    private void startAnim() {
        fraction_earth += 0.003;
        if(fraction_earth >= 1){
            fraction_earth = 0;
        }

        fraction_moon += 0.006;
        if(fraction_moon >= 1){
            fraction_moon = 0;
        }

        invalidate();
    }


    /**
     * 畫圖片
     * @param canvas
     */
    private void drawBitmap(Canvas canvas, Path path, float fraction){
        PathMeasure measure = new PathMeasure(path, false);
        Matrix mMatrixBitMap = new Matrix();
        //獲取角度和路徑
        measure.getMatrix(measure.getLength() * fraction, mMatrixBitMap,
                PathMeasure.TANGENT_MATRIX_FLAG | PathMeasure.POSITION_MATRIX_FLAG);

        // 將圖片繪製中心調整到與當前點重合(注意:此處是前乘pre)
        mMatrixBitMap.preTranslate(- mBitmap.getWidth() / 2, - mBitmap.getHeight() / 2);

        canvas.drawBitmap(mBitmap, mMatrixBitMap, mPaintCircle);

    }

    /**
     * 畫月球
     * @param canvas
     * @param mPath2
     * @param fraction
     */
    private void drawPlanetMoon(Canvas canvas, Path mPath2, float fraction) {
        PathMeasure pathMeasure2 = new PathMeasure();
        float[] pos2 = new float[2];
        float[] tan2 = new float[2];
        Matrix matrix2 = new Matrix();

        //測量座標和角度
        pathMeasure2.setPath(mPath2, false);
        pathMeasure2.getPosTan(pathMeasure2.getLength() * fraction, pos2, tan2);
        //設置shader
        matrix2.setRotate(360 * fraction);
        RadialGradient mRadialGradient2 = new RadialGradient(pos2[0], pos2[1], 30, new int[]{0x0000FF00, 0xFF00FF00}, null, Shader.TileMode.MIRROR);
        mPaintTwo.setShader(mRadialGradient2);
        mRadialGradient2.setLocalMatrix(matrix2);

        //繪製月球
        canvas.drawCircle(pos2[0], pos2[1], 30, mPaintTwo);
    }

    /**
     * 畫地球
     * @param canvas
     */
    private void drawPlanetEarth(Canvas canvas, Path path1) {
        PathMeasure pathMeasure1 = new PathMeasure();
        float[] pos1 = new float[2];
        float[] tan1 = new float[2];
        Matrix matrix1 = new Matrix();
        //測量座標和角度
        pathMeasure1.setPath(path1, false);
        pathMeasure1.getPosTan(pathMeasure1.getLength() * fraction_earth, pos1, tan1);
        //旋轉shader
        matrix1.setRotate(360 * fraction_earth);
        RadialGradient mRadialGradient1 = new RadialGradient(pos1[0] + 10, pos1[1] + 10, 50, new int[]{0x000000FF, 0xFF0000FF}, null, Shader.TileMode.MIRROR);
        mPaintOne.setShader(mRadialGradient1);
        mRadialGradient1.setLocalMatrix(matrix1);
        //畫地球
        canvas.drawCircle(pos1[0], pos1[1], 50, mPaintOne);


        //---畫地球的衛星月球--------------
        //畫月球圓形軌道
        Path path = drawPlanetPathWayCircle(canvas, pos1[0], pos1[1], 100);

        //畫圖片
        drawBitmap(canvas, path, fraction_moon);

        //畫月球
        drawPlanetMoon(canvas, path, fraction_moon);

    }

    /**
     * 畫太陽
     */
    private void drawSun(Canvas canvas) {
        //創建Shader
        RadialGradient mRadialGradientSun = new RadialGradient(20, 20, 100, new int[]{0x00ff0000, 0xffff0000}, null, Shader.TileMode.MIRROR);
        //創建Matrix
        Matrix matrixSun = new Matrix();
        //旋轉
        matrixSun.setRotate(360 * fraction_earth);
        //Shader設置Matrix
        mRadialGradientSun.setLocalMatrix(matrixSun);
        //畫筆設置Shader
        mPaintSun.setShader(mRadialGradientSun);
        //繪製太陽
        canvas.drawCircle(0, 0, 100, mPaintSun);
    }


    /**
     * 繪製圓圈路徑
     * @param canvas 畫筆
     * @param x 圓心X座標
     * @param y 圓心Y座標
     * @param radius 圓半徑
     */
    private Path drawPlanetPathWayCircle(Canvas canvas, float x, float y, int radius){
        Path path = new Path();
        //畫圓
        path.addCircle(x, y, radius, Path.Direction.CW);
        canvas.drawPath(path, mPaintCircle);
        return path;
    }

    /**
     * 繪製橢圓路徑
     * @param canvas
     * @param left
     * @param top
     * @param right
     * @param bottom
     * @return
     */
    private Path drawPlanetPathWayOval(Canvas canvas, float left, float top, float right, float bottom){
        Path path = new Path();
        //畫橢圓
        path.addOval(left, top, right, bottom, Path.Direction.CW);
        canvas.drawPath(path, mPaintCircle);
        return path;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章