在 Android 中画一个尖角的心
Drawing a Heart with Sharp Corner in Android
下面的问题可能听起来有点愚蠢,但我想愚蠢是没有限制的,所以就这样吧。我在 Android 中使用 Canvas 画了一颗心,在画心时没有遇到任何问题,但我无法在交汇点使心尖锐。我的心像
代码:
left_x_moveto = 200;
left_y_moveto = 45;
left_x1 = 197;
left_y1 = -35;
left_x2 = 60;
left_y2 = 20;
left_x3 = 193;
left_y3 = 130;
right_x_moveto = 200;
right_y_moveto = 45;
right_x1 = 197;
right_y1 = -35;
right_x2 = 345;
right_y2 = 20;
right_x3 = 193;
right_y3 = 130;
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.moveTo(right_x_moveto, right_y_moveto);
path.cubicTo(right_x1, right_y1, right_x2, right_y2, right_x3, right_y3);
canvas.drawPath(path, heart_outline_paint);
到目前为止我尝试了什么:
- 减少或增加
left_x_moveto
,left_y_moveto
的点数,反之亦然,但心已完全毁容,我找不到原因。
当right_x_moveto = 198
和right_y_moveto = 45
时,心的样子
我不确定为什么会这样。
- 减少
heart_outline_paint
的宽度会得到我想要的,但我希望 心的厚度 相同,所以减少 setStrokeWidth
不是一个选项。
简而言之,我希望两条曲线都相遇并合并,而不仅仅是相遇。
任何帮助都感激不尽。提前致谢。
发生的情况是线的粗细是在一侧绘制的,而不是在两侧绘制的。在真正的 MS 绘画时尚中:
(左边是正在发生的事情,右边是你想要的。黑色是线的实际位置,宽度为 1px,红色是 "padding",第 2、3 到第 15 个像素,heart_outline_paint.setStrokeWidth(15);
)
要解决此问题,请尝试从右线的 x 减去线宽的一半,并将其添加到左线的 x。这样做会解决这个问题,而不是解决它
你需要执行几个这样的操作。
- 通过
path.close()
关闭路径。
- 您需要通过
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
设置笔画连接
一个path
只有连续绘制才能关闭。因此,我修改了代码,以便 path.close()
可以正确完成。下面是代码。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
path = new Path();
int left_x_moveto = 200;
int left_y_moveto = 45;
int left_x1 = 180;
int left_y1 = -20;
int left_x2 = 30;
int left_y2 = 20;
int left_x3 = 193;
int left_y3 = 130;
int right_x_moveto = 200;
int right_y_moveto = 45;
int right_x1 = 214;
int right_y1 = -20;
int right_x2 = 375;
int right_y2 = 20;
int right_x3 = 193;
int right_y3 = 130;
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.cubicTo(right_x2, right_y2, right_x1, right_y1, right_x_moveto, right_y_moveto);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
Paint.Join.MITER
是做你想做的那个。
The outer edges of a join meet at a sharp angle
现在这个 MITER
连接仅在角度 <= 90 度时有效。但在这里,根据您提供的值,角度为 90 度,因此 MITER
连接不起作用。我修改了值以获得下图。图像不准确,但您需要尝试使用正确的值。
您可以设置 ROUND
加入方法来获得以下内容。
问题出在 Path.cubicTo()
。在不压扁心形的情况下很难让 MITTER
加入工作。因此,我尝试使用 lineTo
和 arcTo
而不是 cubicTo
来创建一颗简单的心。下面是它的代码。您会注意到我将 canvas 旋转了 45 度,然后绘制了心形。这纯粹是为了方便,让坐标简单,不涉及毕达哥拉斯定理。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path = new Path();
float length = 100;
float x = canvas.getWidth()/2;
float y = canvas.getHeight()/2;
canvas.rotate(45,x,y);
path.moveTo(x,y);
path.lineTo(x-length, y);
path.arcTo(new RectF(x-length-(length/2),y-length,x-(length/2),y),90,180);
path.arcTo(new RectF(x-length,y-length-(length/2),x,y-(length/2)),180,180);
path.lineTo(x,y);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
这段代码的最终渲染图如下:
下面的问题可能听起来有点愚蠢,但我想愚蠢是没有限制的,所以就这样吧。我在 Android 中使用 Canvas 画了一颗心,在画心时没有遇到任何问题,但我无法在交汇点使心尖锐。我的心像
代码:
left_x_moveto = 200;
left_y_moveto = 45;
left_x1 = 197;
left_y1 = -35;
left_x2 = 60;
left_y2 = 20;
left_x3 = 193;
left_y3 = 130;
right_x_moveto = 200;
right_y_moveto = 45;
right_x1 = 197;
right_y1 = -35;
right_x2 = 345;
right_y2 = 20;
right_x3 = 193;
right_y3 = 130;
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.moveTo(right_x_moveto, right_y_moveto);
path.cubicTo(right_x1, right_y1, right_x2, right_y2, right_x3, right_y3);
canvas.drawPath(path, heart_outline_paint);
到目前为止我尝试了什么:
- 减少或增加
left_x_moveto
,left_y_moveto
的点数,反之亦然,但心已完全毁容,我找不到原因。
当right_x_moveto = 198
和right_y_moveto = 45
时,心的样子
我不确定为什么会这样。
- 减少
heart_outline_paint
的宽度会得到我想要的,但我希望 心的厚度 相同,所以减少setStrokeWidth
不是一个选项。
简而言之,我希望两条曲线都相遇并合并,而不仅仅是相遇。 任何帮助都感激不尽。提前致谢。
发生的情况是线的粗细是在一侧绘制的,而不是在两侧绘制的。在真正的 MS 绘画时尚中:
(左边是正在发生的事情,右边是你想要的。黑色是线的实际位置,宽度为 1px,红色是 "padding",第 2、3 到第 15 个像素,heart_outline_paint.setStrokeWidth(15);
)
要解决此问题,请尝试从右线的 x 减去线宽的一半,并将其添加到左线的 x。这样做会解决这个问题,而不是解决它
你需要执行几个这样的操作。
- 通过
path.close()
关闭路径。 - 您需要通过
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
设置笔画连接
一个path
只有连续绘制才能关闭。因此,我修改了代码,以便 path.close()
可以正确完成。下面是代码。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
path = new Path();
int left_x_moveto = 200;
int left_y_moveto = 45;
int left_x1 = 180;
int left_y1 = -20;
int left_x2 = 30;
int left_y2 = 20;
int left_x3 = 193;
int left_y3 = 130;
int right_x_moveto = 200;
int right_y_moveto = 45;
int right_x1 = 214;
int right_y1 = -20;
int right_x2 = 375;
int right_y2 = 20;
int right_x3 = 193;
int right_y3 = 130;
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.cubicTo(right_x2, right_y2, right_x1, right_y1, right_x_moveto, right_y_moveto);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
Paint.Join.MITER
是做你想做的那个。
The outer edges of a join meet at a sharp angle
现在这个 MITER
连接仅在角度 <= 90 度时有效。但在这里,根据您提供的值,角度为 90 度,因此 MITER
连接不起作用。我修改了值以获得下图。图像不准确,但您需要尝试使用正确的值。
您可以设置 ROUND
加入方法来获得以下内容。
问题出在 Path.cubicTo()
。在不压扁心形的情况下很难让 MITTER
加入工作。因此,我尝试使用 lineTo
和 arcTo
而不是 cubicTo
来创建一颗简单的心。下面是它的代码。您会注意到我将 canvas 旋转了 45 度,然后绘制了心形。这纯粹是为了方便,让坐标简单,不涉及毕达哥拉斯定理。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path = new Path();
float length = 100;
float x = canvas.getWidth()/2;
float y = canvas.getHeight()/2;
canvas.rotate(45,x,y);
path.moveTo(x,y);
path.lineTo(x-length, y);
path.arcTo(new RectF(x-length-(length/2),y-length,x-(length/2),y),90,180);
path.arcTo(new RectF(x-length,y-length-(length/2),x,y-(length/2)),180,180);
path.lineTo(x,y);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
这段代码的最终渲染图如下: