西部数码主机 | 阿里云主机| 虚拟主机 | 服务器 | 返回乐道官网

Android中Canvas绘图之Shader使用图文详解

时间:2016-01-15 08:33来源:未知 作者:好模板 点击:
我们在用Android中的Canvas绘制各种图形时,可以通过Paint.setShader(shader)方法为画笔Paint设置shader,这样就可以绘制出多彩的图形。那么Shader是什么呢?做过GPU绘图的同学应该都知道这个词

我们在用Android中的Canvas绘制各种图形时,可以通过Paint.setShader(shader) 方法为画笔Paint设置shader,这样就可以绘制出多彩的图形。那么Shader是什么呢?做过GPU绘图的同学应该都知道这个词汇,Shader就是着色器的意思。我们可以这样理解,Canvas中的各种drawXXX方法定义了图形的形状,画笔中的Shader则定义了图形的着色、外观,二者结合到一起就决定了最终Canvas绘制的被色彩填充的图形的样子。

类 android.graphics.Shader 有五个子类,分别是:BitmapShader、LinearGradient、RadialGradient、SweepGradient和ComposeShader,下面依次对这几个类的使用分别说明。

BitmapShader

BitmapShader,顾名思义,就是用Bitmap对绘制的图形进行渲染着色,其实就是用图片对图形进行贴图。

BitmapShader构造函数如下所示:

BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

第一个参数是Bitmap对象,该Bitmap决定了用什么图片对绘制的图形进行贴图。

第二个参数和第三个参数都是Shader.TileMode类型的枚举值,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。

  • CLAMPCLAMP表示,当所画图形的尺寸大于Bitmap的尺寸的时候,会用Bitmap四边的颜色填充剩余空间。

    我们有一个Bitmap,如下所示:

    注意,我们这张图片的四个角是有一定的圆弧的,也就是该Bitmap的四个角点处的像素都是透明的。我们使用该Bitmap,演示TileMode为CLAMP的效果,代码如下所示:

    BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    paint.setShader(bitmapShader);
    canvas.drawRect(0, 0, bitmap.getWidth() * 2, bitmap.getHeight() * 2, paint);

    效果如下所示:

    我们可以看到,由于我们所绘制的矩形矩形区域比Bitmap大,Bitmap就用右侧边和下侧边的最外层的颜色填充了矩形区域。由于原Bitmap右下角的像素是透明的,所以绘制的矩形的右下角就用透明填充了。

    如果我们绘制的图形尺寸小于Bitmap尺寸,那么效果看起来就像是对原Bitmap裁剪了一下而已,代码如下所示:

    我们可以看到,当我们所绘制的圆形尺寸小于Bitmap尺寸的时候,看起来的效果就是我们用所绘制的圆形对Bitmap进行了裁剪。

  • REPEAT

    REPEAT表示,当我们绘制的图形尺寸大于Bitmap尺寸时,会用Bitmap重复平铺整个绘制的区域。

    示例代码如下所示:

    BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
    paint.setShader(bitmapShader);
    canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

    效果如下所示:

  • MIRROR

    与REPEAT类似,当绘制的图形尺寸大于Bitmap尺寸时,MIRROR也会用Bitmap重复平铺整个绘图区域,与REPEAT不同的是,两个相邻的Bitmap互为镜像。

    代码如下所示:

    BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
    paint.setShader(bitmapShader);
    canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

    效果如下所示:

最后需要说的是,在构造BitmapShader时,tileX和tileY可以取不同的值,二者不用非得一致。

LinearGradient

我们可以用LinearGradient创建线性渐变效果,其有两个构造函数:

LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)

我们重点说一下第一个构造函数,在此基础上理解第二个构造函数就很简单了。

LinearGradient是用来创建线性渐变效果的,它是沿着某条直线的方向渐变的,坐标(x0,y0)就是这条渐变直线的起点,坐标(x1,y1)就是这条渐变直线的终点。需要说明的是,坐标(x0,y0)和坐标(x1,y1)都是Canvas绘图坐标系中的坐标。color0和color1分别表示了渐变的起始颜色和终止颜色。与BitmapShader类似,LinearGradient也支持TileMode,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。

使用代码如下所示:

LinearGradient linearGradient = new LinearGradient(100, 100, 500, 500, Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
canvas.drawRect(100, 100, 500, 500, paint);

效果如下所示:

上面我们使用了CLAMP,但是由于我们绘制的矩形与渐变位置的大小一样大,所以CLAMP效果不明显。

我们把绘制的区域变大,还是用CLAMP,这次绘制整个Canvas大小的矩形。

canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

效果如下所示:

当我们把CLAMP改为REPEAT时,还是绘制整个Canvas大小的矩形,效果如下所示:

当我们用MIRROR绘制整个Canvas大小的矩形的时候,效果如下所示:

在LinearGradient的第二个构造函数中可以通过参数colors传入多个颜色值进去,这样就会用colors数组中指定的颜色值一起进行颜色线性插值。还可以指定positions数组,该数组中每一个position对应colors数组中每个颜色在线段中的相对位置,position取值范围为[0,1],0表示起始位置,1表示终止位置。如果positions数组为null,那么Android会自动为colors设置等间距的位置。

RadialGradient

我们可以用RadialGradient创建从中心向四周发散的辐射渐变效果,其有两个构造函数:

RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)

RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)

这两个构造函数和LinearGradient的两个构造函数很类似,我们此处还是重点讲解第一个构造函数,在此基础上理解第二个构造函数就很简单了。

RadialGradient是用来创建从中心向四周发散的辐射渐变效果的,所以我们需要在其构造函数中传入一些圆的参数,坐标(centerX,centerY)是圆心,即起始的中心颜色的位置,radius确定了圆的半径,在圆的半径处的颜色是edgeColor,这样就确定了当位置从圆心移向圆的轮廓时,颜色逐渐从centerColor渐变到edgeColor。RadialGradient也支持TileMode参数,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。

我们首先将CLAMP作为TileMode,代码如下所示:

int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
float centerX = canvasWidth / 2f;
float centerY = canvasHeight / 2f;
float radius = canvasWidth / 4f;
RadialGradient radialGradient = new RadialGradient(centerX, centerY, radius, Color.GREEN, Color.BLUE, Shader.TileMode.MIRROR);
paint.setShader(radialGradient);
canvas.drawRect(0, 0, canvasWidth, canvasHeight, paint);

效果如下所示:

在上图中,我们绘制的矩形和Canvas大小一样大,其尺寸大于我们定义的RadialGradient的圆的尺寸。我们可以看到,当使用CLAMP作为TileMode时,颜色从圆心的绿色向圆周的蓝色渐变,在圆以外的空间都用edgeColor蓝色填充。
(责任编辑:好模板)

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
热点内容