【问题标题】:Android - Fill Path with color partiallyAndroid - 部分用颜色填充路径
【发布时间】:2023-04-10 00:11:01
【问题描述】:

我正在尝试使用 Android 中的 Path 绘制心形画布。代码如下:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        // Fill the canvas with background color
        canvas.drawColor(Color.WHITE);
       // paint.setShader(null);

        // Defining of  the heart path starts
        path.moveTo(left + WIDTH / 2, top + HEIGHT / 4); // Starting point
        // Create a cubic Bezier cubic left path
        path.cubicTo(left+WIDTH/5,top,
                left+WIDTH/4,top+4*HEIGHT/5,
                left+WIDTH/2, top+HEIGHT);
        // This is right Bezier cubic path
        path.cubicTo(left + 3 * WIDTH / 4, top + 4 * HEIGHT / 5,
                left + 4 * WIDTH / 5, top,
                left + WIDTH / 2, top + HEIGHT / 4);

         paint.setShader(new LinearGradient(0, canvas.getHeight()/4, canvas.getWidth(), canvas.getHeight()/4, new int[]{Color.RED, Color.YELLOW, Color.GREEN}, new float[]{0, 0.6f, 1}, Shader.TileMode.CLAMP));

        canvas.drawPath(path, paint);

        heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
        heart_outline_paint.setStrokeWidth(4);
        heart_outline_paint.setStyle(Paint.Style.STROKE);
        canvas.drawPath(path, heart_outline_paint);



    }

我可以毫无问题地绘制心脏,并且可以使用 Paint 中的 Fill 选项在心脏内部填充颜色。但是我应该可以根据一些数据动态填满心脏,不能一直填满。我目前取得的成果如下:

我进行了广泛的搜索,发现了很多类似的事情。其中一些包括:

  1. Android fill in part of a path?
  2. filling a circle gradually from bottom to top android

我还遇到了将画布转换为位图并使用Flood Fill Algorithm 在位图中填充颜色的概念,它允许用户在位图中填充颜色。但是,我不希望位图在触摸心脏内部时填充颜色,而是在按钮单击动作时填充。

我以为filling a circle gradually from bottom to top android 会帮助我,但它使用了一个圆圈,而且我对 Canvas 并不精通,这使我在将圆圈代码适应这种形状方面非常薄弱。

如果有人对如何实现这一点有一些想法或任何见解,那将非常有帮助。干杯。提前致谢。

P.S : 我还尝试了一些在 Paint 中使用 setShader 的技巧,但没有什么能满足我的需求。

编辑:

我偶然发现了一个想法,用另一种与画布背景相同的颜色在心脏上绘制一个矩形,这样它看起来就像是半填充的!我仍在研究这个想法,不确定这对我来说有多准确。如果有人有更好的想法,欢迎您。

【问题讨论】:

  • "But I should be able to fill the heart dynamically according to some data and it cannot be filled fully all the time." 在实践中意味着什么?
  • 就像心脏必须填充 10% 或 20% 取决于用户获得的点数。
  • 我使用了你提到的在心形填充上绘制一个矩形,但在心形边框后面。对我来说效果很好。

标签: android bitmap android-canvas


【解决方案1】:

我使用了 Canvas 中提供的 clipPath 函数来实现我所需要的。我用上面的方法画了心脏,在上面画了一个矩形,然后我用clipPath函数把心脏以外的区域剪掉了。

     public static double filled_amount = .90;
     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, left_x_moveto, left_y_moveto);
     path.close();
     Rect rect = new Rect((int)(canvas.getWidth()*.10),(int)(canvas.getHeight()*filled_amount),(int) canvas.getWidth(), (int) canvas.getHeight());
        canvas.clipPath(path); 
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawPath(path, paint);
        canvas.drawRect(rect, rect_paint);
        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);
        canvas.drawPath(path, heart_outline_paint);

这将给我动态填充心脏的预期结果。动态更改filled_amount 的值并调用invalidate() 将使它看起来像是在动态填充心脏。

@Henry 的回答可能会更好,但这对我有用,而且我没有深入研究边缘,所以这里有点曲折,没关系。

【讨论】:

    【解决方案2】:

    您可以使用Bitmap Masking 来获得部分填充的心。您在这里理想地做的是使用一个位图来掩盖另一个。

    在您的情况下,您可以在画布中有一个填充的矩形,然后您在一个新的位图中有一个 heart 形状作为蒙版。然后,您可以通过更改背景矩形的高度来动态更改心形的填充。

    请参考:https://stackoverflow.com/a/33483600/4747587。这包含部分填充星形的实现。思路是一样的。

    【讨论】:

    • 感谢您的回答,我是通过使用 Canvas 中的 Path 和 clipPath 函数实现的。
    • 是的。但是clipPath 不支持抗锯齿。根据不同的形状,您可能会开始看到锯齿形边缘。如果您不了解太多细节,并且形状合适,那么clipPath 就可以了。
    • 我不太了解细节,所以 clipPath 非常适合我,不过感谢您的宝贵建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 2013-07-23
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多