简体   繁体   English

如何剪辑canvas.drawCircle()而不剪切阴影?

[英]How to clip a canvas.drawCircle() without clipping the shadow?

Here's simplified version of my code: 这是我的代码的简化版本:

Paint p = new Paint();

p.setShader(borderShader); //use a bitmap as a texture to paint with
p.setFilterBitmap(true);
p.setShadowLayer(20, 20, 20, Color.BLACK);

canvas.clipRect(10,0,width-10,height);
canvas.drawCircle(width/2,height/2,1000/2,p);

So the image looks something like this: 所以图像看起来像这样:

在此输入图像描述

A circle that's clipped on both sides. 两侧都有一个圆圈。

The problem is, since the shadow is ofset by 20 pixels down, and 20 pixels to the right. 问题是,因为阴影下降20个像素,右侧20个像素。 The right portion of the shadow is clipped by the clipRect and won't show. 阴影的右侧部分被clipRect剪切,不会显示。

I have to use clipRect instead of simply drawing a white rectangle to clip the circle because the left and right of the circle needs to be transparent to display the background underneath. 我必须使用clipRect而不是简单地绘制一个白色矩形来剪裁圆圈,因为圆圈的左边和右边需要透明才能显示下面的背景。

I ended up using Path to draw the shape by using two arcs and two line segments instead of using rectangular clipping areas on a circle. 我最终使用Path通过使用两个弧和两个线段来绘制形状,而不是使用圆上的矩形剪切区域。

A lot of trig and math later, it works perfectly. 很多触发和数学之后,它完美地运作。

EDIT: 编辑:

Per request, here is a sample of the code I ended up using. 根据请求,这是我最终使用的代码示例。 Note that this is custom tailored to my application and will work to draw out a shape exactly like the one in my question. 请注意,这是根据我的应用程序定制的,并且可以绘制出与我的问题中的形状完全相同的形状。

private void setupBorderShadow()
{
    //Set up variables
    int h = SUI.WIDTH / 2; // x component of the center of the circle 
    int k = SUI.HEIGHT_CENTER; // y component of the center of the circle

    int x = SUI.WIDTH / 2 - 4 * SUI.CIRCLE_RADIUS_DIFFERENCE - SUI.BORDER_WIDTH; //left side of the rectangle
    int r = 6 * SUI.CIRCLE_RADIUS_DIFFERENCE + SUI.BORDER_WIDTH; //radius of circle


    //define a rectangle that circumscribes the circle
    RectF circle = new RectF(h - r, k - r, h + r, k + r);

    Path p = new Path();
    //draw a line that goes from the bottom left to the top left of the shape
    p.moveTo(x, (float) (k + Math.sqrt(-(h * h) + 2 * h * x + r * r - (x * x))));
    p.lineTo(x, (float) (k - Math.sqrt(-(h * h) + 2 * h * x + r * r - (x * x))));

    //calculate the angle that the top left of the shape represents in the circle
    float angle = (float) Math.toDegrees(Math.atan(Math.sqrt(-(h * h) + 2 * h * x + r * r
            - (x * x))
            / (h - x)));

    //draw an arc from the top left of shape to top right of shape 
    p.arcTo(circle, 180 + angle, (180 - angle * 2));

    // the x component of the right side of the shape
    x = SUI.WIDTH / 2 + 4 * SUI.CIRCLE_RADIUS_DIFFERENCE + SUI.BORDER_WIDTH;

    //draw line from top right to bottom right
    p.lineTo(x, (float) (k + Math.sqrt(-(h * h) + 2 * h * x + r * r - (x * x))));

    //draw arc back from bottom right to bottom left. 
    p.arcTo(circle, angle, (180 - angle * 2));


    //draw the path onto the canvas
    _borderCanvas.drawPath(p, SUI.borderShadowPaint);
}

Note that some of the variables that I use such as "CIRCLE_RADIUS_DIFFERENCE" might not make sense. 请注意,我使用的某些变量(如“CIRCLE_RADIUS_DIFFERENCE”)可能没有意义。 Ignore these, they are app specific constants. 忽略这些,它们是app特定的常量。 All the variables that actually make a difference in the geometric calculations are labeled. 实际上在几何计算中产生差异的所有变量都被标记出来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM