之前在手機上下了個輸入數學函數就可以直接繪製出函數圖形的app,發現裏面必須要求解出y,才能繪製出圖形,但是有些很複雜的函數不容易也根本不需要轉換成f(x)的形式,比如 心形函數:
(17*(x^2))-(16*|x|*y)+(17*(y^2))<255 ; x(-5,5) y(-5,5)(心形函數式)
想看看這個函數的形狀,但是本學渣根本不知道怎麼解啊。。。還好我是個程序員,我可以自己畫出來嘛。把方程看作一個判斷然後繪製就行了。
下面是實現的代碼:
1、首先在構造方法中創建一個自己的畫板,paint和用來繪製心形的bitmap(這個bitmap是可變化的,canvas.drawxxx後bitmap會自動改變),用這種bitmap方式,是爲了產生動畫效果。然後開啓一個線程,去判斷函數式,描點繪製到我們的畫板上。
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(5f);
mBitmap = Bitmap.createBitmap(500,500, Bitmap.Config.ARGB_8888); //生成一個bitmap
mCanvas = new Canvas(mBitmap);
new Thread(){
@Override
public void run() {
super.run();
drawLove(mCanvas);
}
}.start();
}
2 繪製心形的核心方法:
判斷思路是這樣的,首先根據方程xy取值範圍 把圖形分爲 4塊(4個象限),2個for循環遍歷一個象限的所有點,縮小實際座標,得到方程範圍的值,根據方程判斷出符合的座標,然後描點,下面判斷了兩個一個是y>0, 還一個是y<0,裏面加250,是因爲手機座標原點是從左上角開始,所以原點平移到左上角,xy要加平移的距離
private void drawLove(Canvas canvas) {
//(17*(x^2))-(16*abs(x)*y)+(17*(y^2))<255 x(-5,5) y(-5,5) (心形函數方程式)
int loveWidth = 500;//心型寬度,必須是偶數
int oneLine = loveWidth/2;//一條軸長度
float scale = oneLine/5f;//實際座標比上方程式座標,倍數
for (int i = 0; i < oneLine; i++) {
for (int j = 0; j < oneLine; j++) {
//根據表達式xy的範圍,所以要把座標系的範圍也縮小
float xf = i/scale;
float yf = j/scale;
if((17*Math.pow(xf, 2) - 16*Math.abs(xf)*yf+17*Math.pow(yf, 2))<255){
//右上1
// canvas.drawPoint(xf*scale+250,250+yf*scale, paint);
//左下2
canvas.drawPoint(250-xf*scale,250-yf*scale, mPaint);
// this.postInvalidateDelayed(10);
//右上1
// canvas.drawPoint(-xf*scale+250,250+yf*scale, paint);
//右下2
canvas.drawPoint(250+xf*scale,250-yf*scale, mPaint);
// this.postInvalidateDelayed(10);
// Log.i("TAG", "xf-->"+(xf*scale+250)+"yf-->"+(250-yf*scale));
}
if((17*Math.pow(xf, 2) - 16*Math.abs(xf)*(-yf)+17*Math.pow(yf, 2))<255){
//左上2
canvas.drawPoint(250-xf*scale, 250+yf*scale, mPaint);
//右下 1
// canvas.drawPoint(250+xf*scale,250-yf*scale, paint);
// this.postInvalidateDelayed(10);
//左上2
canvas.drawPoint(250+xf*scale, 250+yf*scale, mPaint);
//右下 1
// canvas.drawPoint(250-xf*scale,250-yf*scale, paint);
// this.postInvalidateDelayed(10);
}
//延時刷新,產生動畫效果
delayedTime();
this.postInvalidate();
}
}//end for
}
3、重寫onDraw(這個很簡單,就一句話)
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, new Matrix(), mPaint);
}//end onDraw
private void delayedTime() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
效果圖:
Demo下載地址:點擊打開鏈接