根據圓心座標以及手指座標計算圓上點的位置
阿新 • • 發佈:2019-01-26
前些天朋友讓我幫忙做一個功能“根據圖上的點獲取相應的顏色”,點是可拖動的,並且是以圓的形式做規律運動的,以前也沒做過,所以想了很多方法都沒實現,最後參考了別人的以角度算位置才算解決了。
先說說需求
在內圓或外圓中有個點,可以拖動,點一直在兩條線的中間位置。
解決方案,自定義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(floatcenterX, 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內的程式碼獲取到了夾角的度數。