沿路径使用渐变

时间:2011-06-24 13:49:05

标签: android graphics path gradient shader

我正在尝试使用Android Path类创建'glow'效果。但是,渐变不会扭曲以适应路径。相反,它只是显示在“上方”并剪切到路径的笔划。使用方形路径,下面的图像显示了我的意思:

Path-gradient fail

相反,它看起来应该更像这样:

enter image description here

换句话说,渐变遵循路径,特别是根据CornerPathEffect中设置的半径包围角落。

以下是代码的相关部分:

paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(20);
paint.setAntiAlias(true);
LinearGradient gradient = new LinearGradient(30, 0, 50, 0,
    new int[] {0x00000000, 0xFF0000FF, 0x00000000}, null, Shader.TileMode.MIRROR);
paint.setShader(gradient);
PathEffect cornerEffect = new CornerPathEffect(10);
paint.setPathEffect(cornerEffect);
canvas.drawPath(boxPath, paint);

有什么想法吗?


另一种选择是在定义笔划宽度时获得“软边刷”效果。我已经尝试过BlurMaskFilters,但是那些会产生统一的模糊,而不是从不透明到透明的过渡。有谁知道这是否可能?

4 个答案:

答案 0 :(得分:4)

用软刷位图绘制怎么样?使用像Photoshop这样的图像编辑软件,制作一个柔和的圆形刷,其不透明度径向向外减小保存为可绘制,将其加载到位图中,并沿着路径均匀地绘制它。用白色画笔制作位图。这样,您可以使用PorterDuffColorFilter简单地将给定颜色(此处为蓝色)乘以您的位图。

brush1=BitmapFactory.decodeResource(getResources(), R.drawable.brush_custom_one);
//This contains radially decreasing opacity brush
porter_paint.setColorFilter(new PorterDuffColorFilter(paint.getColor(), Mode.MULTIPLY));
for (int i=1;i<matrix.size();i++) {
//matrix contains evenly spaced points along path 
Point point = matrix.get(matrix.get(i));
canvas.drawBitmap(brush1, point.x,point.y, porter_paint);}

使用的画笔是(它在那里):Brush used 最终结果是:Final result

答案 1 :(得分:3)

原来有一种明显的方法可以做到这一点。只需重复使用相同的路径,并在每个绘图过程中调整笔划宽度和alpha。示例代码:

float numberOfPasses = 20;
float maxWidth = 15;
for (float i = 0; i <= numberOfPasses; i++){
    int alpha = (int) (i / numberOfPasses * 255f);
    float width = maxWidth * (1 - i / numberOfPasses);

    paint.setARGB(alpha, 0, 0, 255);
    paint.setStrokeWidth(width);
    canvas.drawPath(path, paint);
}

请参阅下面的结果示例。左路径是使用此方法绘制的,右路径用于比较,使用maxWidth和255 alpha在单个笔划中绘制。

Example of drawing result

这主要有效。有两个问题:

  • 渐变不是那么平滑。这是因为每次传递被绘制在前一个传递上导致alpha构建过快,在最终笔划之前达到255。使用第int alpha = (int) (i / numberOfPasses * 125f);行进行试验(注意更改为125f而不是255f)会有所帮助。

  • 路径看起来像是在角落里面“切割”了。可能是CornerPathEffect已应用的结果。

答案 2 :(得分:2)

如果我理解的话,你想要做的是让渐变有效地形成笔画的“画笔”。

完全我最近也试图实现的,但据我所知,API并没有提供任何直接的方法来实现它。我最近创建了一个SVG到Android Canvas转换器类,所以我最近也在Inkscape中工作了很多。所以,当我调查它时,我想知道是否有可能在Inkscape中完成它。然而,即使在Inkscape中,这也是一件非常重要的事情。经过一些搜索后,我最终看到了一个沿路径过程应用的渐变图像,以及下面教程的下载链接:

http://www.flickr.com/photos/35772571@N03/3312087295/

我当时亲自尝试做的是制作一些半圆形,其中路径是一种霓虹灯发光而不是平面颜色。根据Android API和SVG标准进行讨论,似乎唯一的方法是创建一个完美居中于圆圈的径向渐变,并在一个正确的位置放置一系列色块。非常棘手,我当然不知道你是怎么做到像方形的形状。

对不起,这有点像'我做不到',而不是一个有用的答案!我会兴趣地关注这个,因为我也渴望知道一种“软刷”效果的解决方案。

答案 3 :(得分:0)

绘制渐变比遵循路径非常复杂。 因此,我建议您使用一些已经完成的库而不是为您自己做。 一个可以是Sc-Gauges

进行一些有用的分类,以达到目标。

首先包含库:

dependencies {
    ...
    compile 'com.github.paroca72:sc-gauges:3.0.7'
}

创建图像或在画布上绘制所需的图像后:

<ImageView
      android:id="@+id/image"
      android:layout_width="match_parent"
      android:layout_height="match_parent" 
/>

现在输入代码:

    // Dimensions
    int padding = 24;
    Rect drawArea = new Rect(padding, padding, 700 - padding, 500 - padding);

    // Get the main layout
    ImageView imageContainer = (ImageView) this.findViewById(R.id.image);
    assert imageContainer != null;

    // Create a bitmap and link a canvas
    Bitmap bitmap = Bitmap.createBitmap(
            drawArea.width() + padding * 2, drawArea.height() + padding * 2,
            Bitmap.Config.ARGB_8888
    );
    Canvas canvas = new Canvas(bitmap);
    canvas.drawColor(Color.parseColor("#f5f5f5"));

    // Create the path building a bezier curve from the left-top to the right-bottom angles of
    // the drawing area.
    Path path = new Path();
    path.moveTo(drawArea.left, drawArea.top);
    path.quadTo(drawArea.centerX(), drawArea.top, drawArea.centerX(), drawArea.centerY());
    path.quadTo(drawArea.centerX(), drawArea.bottom, drawArea.right, drawArea.bottom);

    // Feature
    ScCopier copier = new ScCopier();
    copier.setPath(path);
    copier.setColors(Color.RED, Color.GREEN, Color.BLUE);
    copier.setWidths(20);
    copier.draw(canvas);

    // Add the bitmap to the container
    imageContainer.setImageBitmap(bitmap);

结果如下:

enter image description here

代码的第一部分仅用于在绘制位置创建位图。 您感兴趣的是使用ScCopier的第二部分。 只需给出路径,颜色和标记即可。

请注意,您不在视图内,可以使用onDraw直接在视图画布上绘制。

该库可用于创建各种规格。 如果您想看看这个网站,ScComponents会提供一些免费的而非标准的组件。