问题
I tried with following code, But this code is not working as expected. Actually I hesitated to ask help for this simple solution, But I have wasted lots of time, finally I came here.
deltaX = bounds.right - bounds.left;
deltaY = bounds.bottom - bounds.top;
double distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
float arrowLength= (float) (distance / 3);
float lineAngle = (float) Math.atan2(deltaY, deltaX);
float angle = (float) Math.toRadians(20);
float sinValue = (float) Math.sin(lineAngle - angle);
point_x_1 = bounds.left - 20 * sinValue;
point_y_1 = (float) (bounds.bottom - 0.5 * arrowLength* Math.cos(lineAngle - angle));
angle = (float) Math.toRadians(60);
sinValue = (float) Math.sin(lineAngle + angle);
point_x_3 = bounds.left + 20 * sinValue;
point_y_3 = (float) (bounds.bottom + arrowLength* Math.cos(lineAngle + angle));
path.moveTo(bounds.right, bounds.top);
path.lineTo(bounds.left, bounds.bottom);
path.moveTo(point_x_1, point_y_1);
path.lineTo(bounds.left, bounds.bottom);
path.lineTo(point_x_3, point_y_3);
Note: I have four directions, each will come in different scenarios.
enum PathDirection {
TopLeftToBottomRight,
TopRightToBottomLeft,
BottomLeftToTopRight,
BottomRightToTopLeft
}
Above code I tried for TopRightToBottomLeft.
Sample Outputs
Pic 1: RectF values: [180.0,560.0][820.0,740.0]
Pic 2: RectF values: [240.0,480.0][640.0,980.0]
Update
path.reset();
canvas.save();
canvas.translate(200, 200);
float direction = (float) Math.atan2(400 - 200, 400 - 200);
canvas.rotate(direction);
path.moveTo(0, 0);
float distance = (float) Math.sqrt(200 * 200 + 200 * 200);
path.lineTo(distance, 0);
float x1 = distance - (distance * 20 / 100);
float y1 = -(distance * 15 / 100);
path.moveTo(x1, y1);
path.lineTo(distance, 0);
x1 = distance - (distance * 20 / 100);
y1 = (distance * 15 / 100);
path.lineTo(x1, y1);
canvas.drawPath(path, mPaint);
canvas.restore();
I used this code to draw line from from position 200, 200
to 300, 300
. But this draw the line from 0, 0
to distance
.
Screenshot
回答1:
See the javascript code below, that should translate nicely to Java
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
function drawLine(p1, p2, asize) {
ctx.beginPath()
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
if (asize > 0) {
lineAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x);
delta = Math.PI/6
for (i=0; i<2; i++) {
ctx.moveTo(p2.x, p2.y);
x = p2.x + asize * Math.cos(lineAngle + delta)
y = p2.y + asize * Math.sin(lineAngle + delta)
ctx.lineTo(x, y);
delta *= -1
}
}
ctx.stroke();
}
drawLine({x:10, y:10}, {x:100, y:20}, 20)
drawLine({x:20, y:15}, {x:140, y:120}, 20)
drawLine({x:140, y:20}, {x:80, y:50} , 20)
drawLine({x:150, y:20}, {x:150, y:90}, 20)
drawLine({x:180, y:90}, {x:180, y:20}, 20)
drawLine({x:200, y:10}, {x:200, y:140}, 10)
drawLine({x:220, y:140}, {x:220, y:10}, 10)
<canvas id="canvas">
If you run it you should see a few samples.
So let's break it down the drawLine
has 3 parameters (p1, p2, asize)
the first two are the starting-point and end-point of the line, the last one is arrow size, just to give some control to the final user over how big are those arrows at the end.
You had most of the math in your code but it was a bit mixed up, you did calculate the lineAngle
but I got lost in the order of your operations, so better start from scratch.
回答2:
With help from pskink I came to the solution, Sample code, which draw the line with arrow head from 200, 200
to 400, 400
path.reset();
RectF rectF = new RectF(200, 200, 400, 400);
canvas.save();
canvas.translate(rectF.left, rectF.top);
float direction = (float) Math.atan2(rectF.bottom - rectF.top, rectF.right - rectF.left);
float degree = (float) Math.toDegrees(direction);
canvas.rotate(degree);
canvas.drawColor(Color.parseColor("#E3F2FD"));
path.moveTo(0, 0);
float x = rectF.right - rectF.left;
float y = rectF.bottom - rectF.top;
float distance = (float) Math.sqrt(x * x + y * y);
path.lineTo(distance, 0);
float x1 = distance - (distance * 20 / 100);
float y1 = -(distance * 15 / 100);
path.moveTo(x1, y1);
path.lineTo(distance, 0);
float x2 = distance - (distance * 20 / 100);
float y2 = (distance * 15 / 100);
path.lineTo(x2, y2);
canvas.drawPath(path, mPaint);
canvas.restore();
SC:
Note If you don't want to rotate canvas, you can use Helder Sepulveda's answer, it also works as expected.
来源:https://stackoverflow.com/questions/60671113/draw-arrow-head-in-canvas-using-angle