在Android中用锐角绘制一颗心

时间:2015-11-02 08:25:47

标签: android android-canvas

以下问题可能听起来有点愚蠢,但我觉得愚蠢没有限制,所以在这里。我在Android中使用Canvas绘制了一个Heart并且在绘制内心方面没有任何问题,但是我无法在会面点让人心旷神怡。我的心看起来像enter image description here

代码:

            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);

到目前为止我尝试了什么:

  1. 减少或增加left_x_movetoleft_y_moveto的点数,反之亦然,但心脏完全毁容,我无法找到原因。
  2. right_x_moveto = 198right_y_moveto = 45时,心脏看起来像

    enter image description here

    我不确定为什么会这样。

    1. 减少heart_outline_paint的宽度会给我我想要的但我希望心脏的厚度是相同的,所以减少setStrokeWidth不是一个选项
    2. 简而言之,我希望曲线 MEET AND MERGE 而不仅仅是 MEET 。 任何帮助都感激不尽。提前致谢。

2 个答案:

答案 0 :(得分:6)

您需要执行以下几项操作。

  1. 通过path.close()关闭路径。
  2. 您需要通过heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
  3. 设置笔画加入

    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是你想做的事情。

      

    连接的外边缘以锐角相交

    现在,此MITER联接仅在角度<= 90度时有效。但是在这里,根据您提供的值,角度为90度,因此MITER连接不起作用。我修改了值以获得以下图像。图像并不精确,但你需要玩弄正确的值。
    enter image description here


    您可以设置ROUND联接方法以获得以下内容 enter image description here

    问题在于Path.cubicTo()。如果没有让心脏形状受到挤压,很难让MITTER加入工作。因此,我尝试使用cubicTolineTo来创建一个简单的心脏,而不是arcTo。以下是代码。您会注意到我已将画布旋转到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);
    }
    

    此代码的最终渲染图像如下:
    enter image description here

答案 1 :(得分:0)

发生的事情是线的厚度是在一侧绘制的,而不是两者都绘制的。真正的MS涂装方式:

(左边是发生了什么,右边是你想要的。黑色是线的实际位置,宽度为1px,红色是“填充”,第2,第3到第15像素,heart_outline_paint.setStrokeWidth(15);enter image description here

要解决这个问题,请尝试从右边的x减去该线宽的一半,然后将其添加到左边的x。这样做可以解决这个问题,而不是修复它