根据圆心坐标以及手指坐标计算圆上点的位置

前些天朋友让我帮忙做一个功能“根据图上的点获取相应的颜色”,点是可拖动的,并且是以圆的形式做规律运动的,以前也没做过,所以想了很多方法都没实现,最后参考了别人的以角度算位置才算解决了。

先说说需求

在内圆或外圆中有个点,可以拖动,点一直在两条线的中间位置。





解决方案,自定义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内的代码获取到了夹角的度数。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值