gpt4 book ai didi

java - 将 Canvas 上绘制的圆圈旋转到触摸标记的点

转载 作者:行者123 更新时间:2023-11-30 12:06:43 24 4
gpt4 key购买 nike

我试图让我的应用程序显示一个圆圈,用户可以通过触摸并拖动该圆圈来将其旋转到一定程度。假设圆最大可以旋转 60 度,无论哪种方式。

我已经扩展了 View 类来创建我的自定义 View 。我用 drawCircle() 方法在我的 Canvas 上画了一个圆。要旋转它,我知道我必须执行 canvas.rotate(),但我不确定将中心固定为什么。我如何测量这个角度?我旋转什么?

public class DrawingView extends View {

Paint paint;
Canvas canvas;
int originalX = 100;
int originalY = 50;
int radius = 75;
// ... some code ...
// paint, canvas initialised in constructors

@Override
protected void onDraw(Canvas canvas){
canvas.drawCircle(originalX, originalY, radius, paint);
// some more code ...
}

@Override
public boolean onTouchEvent(MotionEvent event){
int x = (int)event.getX();
int y = (int)event.getY();
case MotionEvent.ACTION_DOWN:
// Detect if touch in my circle
break;
case MotionEvent.ACTION_MOVE:
double tx = x - originalX;
double ty = y - originalY;
double tlength = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(radius/tlength);
double degrees = (angle * 180)/Math.PI;
System.out.println("Degrees " + (angle*180)/Math.PI);
break;
}
}

我显示的代码似乎没有给我正确的值。就像,如果我一直触摸并拖动到屏幕的末端,它会给我一个大约 70 度的值。我认为我没有正确计算角度,但我也不知道如何计算。


我按照所选答案的方式寻找角度。然后我在画圆之前使用了 canvas.rotate()。

最佳答案

我不确定我是否了解您对这应该如何运作的想法。但是那里的几何形状肯定很奇怪。 tlength 是从圆心到指压的半径,您正在对它进行 acos。但是,那是错误的。 acos 是哪些值可以为您提供该值的 cos。从理论上讲,这将是不同角度的余弦波。这可能很有趣,但听起来不像你想要的。听起来您想将距离 0 的中心称为旋转 -60 度,将半径旋转 0 度,将 2*radius 旋转 +60 度。所以就这样做吧。您线性插值距离 (60° * (distance/radius)) - 60° 或其他。

虽然从 UI 的角度来看,您最好让用户通过将手指移动到该角度来更改圆上的实际角度。然后将这些值放入 atan2() 并在超出允许范围时对其进行限制。


有很多方法可以做到这一点。您可以根据手指按压来计算角度。因此,您可以使用中心点和当前极坐标等已知点。所以如果你有一个距离为 r 的当前角度,那么另一端的点是 cos(x)*r,如果你有 x 和 sin(y)*r你想要的那个终点的 y 那么到中心的距离是 sqrt(dx*dx + dy*dy) 它所在的角度是 atan2(dy, dx)。所以你可以通过一点三角从极坐标转到笛卡尔坐标。如果您想将圆心和半径之间的差称为角度,您可以对其进行线性插值。


这是一个 View 的快速呈现,它是这样做的。还有其他 UI 选项可以替代,例如不执行实际角度而是更改角度,这样您就可以像移动旋钮或其他东西一样移动圆圈。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class RotateCircleView extends View {
static final double TAU = Math.PI * 2;
Paint paint;
double angle = 0;
double radius = 0;
double ix = Double.NaN, iy = Double.NaN;

public RotateCircleView(Context context) {
super(context);
init();
}
public RotateCircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RotateCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init() {
paint = new Paint();
paint.setAlpha(100);
paint.setStrokeWidth(20);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
ix = w / 2.0;
iy = h / 2.0;
radius = Math.min(ix, iy) / 2.0;
invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
if (Double.isNaN(ix)) return;
super.onDraw(canvas);
canvas.save();
canvas.rotate((float) ((TAU * -angle) / 360.0), (float) ix, (float) iy);
canvas.drawCircle((float) ix, (float) iy, (float) radius, paint);
double limit = TAU / 6.0;
if (angle > limit) angle = limit;
if (angle < -limit) angle = -limit;
double tx = ix + Math.cos(angle) * radius;
double ty = iy + Math.sin(angle) * radius;
canvas.drawLine((float) ix, (float) iy, (float) tx, (float) ty, paint);
canvas.restore();
}

public boolean onTouchEvent(MotionEvent event) {
double mx = event.getX();
double my = event.getY();
double dx = mx - ix;
double dy = my - iy;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
//radius = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
invalidate();
break;
}
return true;
}
}

关于java - 将 Canvas 上绘制的圆圈旋转到触摸标记的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55387714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com