Как нарисовать изогнутую линию между 2 точками на холсте?
Я пробовал много разных подходов из примеров в Интернете, но я не могу заставить это работать. Я пытаюсь сделать метод, который рисует изогнутую линию между 2 точками на холсте. Кривая должна быть определена параметром радиуса.
Ниже мой текущий код.
public OverlayBuilder drawCurvedArrow(int startX, int startY, int endX, int endY, int curveRadius, int padding, int color) {
PointF mPoint1 = new PointF(startX, startY);
PointF mPoint2 = new PointF(endX, endY);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(12);
paint.setColor(color);
Path myPath = new Path();
myPath.moveTo(startX, startY);
myPath.quadTo(mPoint1.x, mPoint1.y, mPoint2.x, mPoint2.y);
canvas.drawPath(myPath, paint);
return this;
}
редактировать
Проблема в том, что я не могу понять, как изогнуть линию, нарисованную на холсте.
3 ответа
Я сам нашел решение своей проблемы. Даже при том, что были некоторые отличные ответы, они не были точным решением моей конкретной проблемы.
Вот что я сделал:
- Нашел точку между 2 заданными точками
- Рассчитан угол 90 градусов между двумя точками
- Вычислили точку X пикселей от средней точки, используя рассчитанный градус из ранее.
- Использовал "path.cubicTo" с этими 3 точками (принимает как отрицательные, так и положительные значения, чтобы определить, каким образом линия должна изгибаться).
Вот мой код, если кто-то должен столкнуться с той же проблемой:
public OverlayBuilder drawCurvedArrow(int x1, int y1, int x2, int y2, int curveRadius, int color, int lineWidth) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(lineWidth);
paint.setColor(ContextCompat.getColor(context, color));
final Path path = new Path();
int midX = x1 + ((x2 - x1) / 2);
int midY = y1 + ((y2 - y1) / 2);
float xDiff = midX - x1;
float yDiff = midY - y1;
double angle = (Math.atan2(yDiff, xDiff) * (180 / Math.PI)) - 90;
double angleRadians = Math.toRadians(angle);
float pointX = (float) (midX + curveRadius * Math.cos(angleRadians));
float pointY = (float) (midY + curveRadius * Math.sin(angleRadians));
path.moveTo(x1, y1);
path.cubicTo(x1,y1,pointX, pointY, x2, y2);
canvas.drawPath(path, paint);
return this;
}
И вот пример того, как выглядит реализация:
Предположим, у вас есть две точки mPoint1 и mPoint2
int w=canvas.getWidth();
int h=canvas.getHeight();
int w_2= (w / 2);
int h_2= (h / 2);
PointF mPoint1 = new PointF(0, 0); //starts at canvas left top
PointF mPoint2 = new PointF(w_2, h_2);//mid of the canvas
Path drawPath1 =drawCurve(mPoint1, mPoint2);
canvas.drawPath(drawPath1, paint);
Способ нарисовать линию
private Path drawCurve(PointF mPointa, PointF mPointb) {
Path myPath = new Path();
myPath.moveTo(mPointa.x, mPointa.y);
final float x2 = (mPointb.x + mPointa.x) / 3;
final float y2 = (mPointb.y + mPointa.y) / 3;
myPath.quadTo(x2, y2, mPointb.x, mPointb.y);
return myPath;
}
Я думаю, что вы используете неправильный метод для этой цели, одно из решений, которое я могу предложить, ниже
float radius = 20;
final RectF oval = new RectF();
oval.set(point1.x - radius, point1.y - radius, point1.x + radius, point1.y+ radius);
Path myPath = new Path();
myPath.arcTo(oval, startAngle, -(float) sweepAngle, true);
а для расчета startAngle вам понадобится
int startAngle = (int) (180 / Math.PI * Math.atan2(point.y - point1.y, point.x - point1.x));
для sweapAngle вы можете найти подробное описание здесь.