1. 程式人生 > >根據圓心座標以及手指座標計算圓上點的位置

根據圓心座標以及手指座標計算圓上點的位置

前些天朋友讓我幫忙做一個功能“根據圖上的點獲取相應的顏色”,點是可拖動的,並且是以圓的形式做規律運動的,以前也沒做過,所以想了很多方法都沒實現,最後參考了別人的以角度算位置才算解決了。

先說說需求

在內圓或外圓中有個點,可以拖動,點一直在兩條線的中間位置。

解決方案,自定義view繼承ImageView,以中心點座標和手指座標計算夾角,以夾角計算點的位置。

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {//獲得初始效果
super.onLayout(changed, left, top, right, bottom);
//獲取中心點座標
    centerX = getWidth()/2;
    centerY = getHeight()/2;
//獲取半徑
    r = (getWidth()/2)-((getWidth()/2)/((ceng+1)*2)+30);
//初始化手指座標點
    X = centerX-50;
    Y = centerY+500;
//通過手指座標點和中心點獲取初始點的位置
    dianY = (int) (r + (r) * Math.cos(Math.PI * (getRotationBetweenLines(centerX,centerY,X,Y)) / 180));
    dianY = (int
) (r + (r) * Math.sin(Math.PI * (getRotationBetweenLines(centerX,centerY,X,Y)) / 180));
//修改手指初始點的位置
    X = dianY;
    Y = dianY;
//設定拖動監聽
    setOnTouchListener(this);
}
/**
 *獲取兩條線的夾角   本方法為往上拷貝的方法,驗證可以使用
 * @param centerX
* @param centerY
* @param xInView
* @param yInView
* @return
*/
public static int getRotationBetweenLines(float 
centerX, float centerY, float xInView, float yInView) { double rotation = 0; double k1 = (double) (centerY - centerY) / (centerX * 2 - centerX); double k2 = (double) (yInView - centerY) / (xInView - centerX); double tmpDegree = Math.atan((Math.abs(k1 - k2)) / (1 + k1 * k2)) / Math.PI * 180; if (xInView > centerX && yInView < centerY) { //第一象限 rotation = 90 - tmpDegree; } else if (xInView > centerX && yInView > centerY) //第二象限 { rotation = 90 + tmpDegree; } else if (xInView < centerX && yInView > centerY) { //第三象限 rotation = 270 - tmpDegree; } else if (xInView < centerX && yInView < centerY) { //第四象限 rotation = 270 + tmpDegree; } else if (xInView == centerX && yInView < centerY) { rotation = 0; } else if (xInView == centerX && yInView > centerY) { rotation = 180; } return (int) rotation; }
@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getActionMasked()){
        case MotionEvent.ACTION_DOWN://獲取手指按下座標並根據座標和點的位置判斷本次操作是否有效
            if (event.getX()<dianX-100||event.getX()>dianX+100||event.getY()<dianY-100||event.getY()>dianY+100){//判斷本次拖動是否有效
t=true;
                break;
            }
            X = (int)event.getX();
            Y = (int)event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            if (t){
                break;
            }
            X = (int)event.getX();
            Y = (int)event.getY();
            if (ceng == 2){//因為圖可能會有兩層顏色所以才加了這個判斷,進入內圈修改半徑就可以了
                if (X>getWidth()/4&&X<getWidth()-(getWidth()/4)&&Y>getWidth()/4&&Y<getWidth()-(getWidth()/4)){
                    r = (getWidth()/2)-((getWidth()/2)/((ceng+1))+30+(getWidth()/2)/((ceng+1)*2));
                }else {
                    r = (getWidth()/2)-((getWidth()/2)/((ceng+1)*2)+30);
                }
            }
            invalidate();//重新整理view實現拖動效果,重新整理時主要是呼叫了view的onDraw方法
break;
        case MotionEvent.ACTION_UP:
            t=false;
            break;
    }
    return true;
}

上面程式碼為頁面初始資料設定
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
//獲取夾角度數
    int dushu = getRotationBetweenLines(centerX,centerY,X,Y)-90;
//根據夾角獲取點的座標
    dianX = (int) (centerX + (r) * Math.cos(Math.PI * dushu / 180));
    dianY = (int) (centerY + (r) * Math.sin(Math.PI * dushu / 180));
    Paint paint = new Paint();
    paint.setAntiAlias(false);
    paint.setColor(Color.RED);
//將點畫在view上
    canvas.drawCircle( dianX, dianY, 10, paint);
    //獲取顏色可以寫在這裡,把介面的方法改一下或者加一個方法就好了
if (rotation != null){//這是介面方便做下一步操作
        rotation.Rotation(dushu);
    }
}
本文中主要程式碼為getRotationBetweenLines內的程式碼獲取到了夾角的度數。