100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 自定义View时 用到Paint Canvas的一些温故 讲讲平时一些效果是怎么画的(基础篇

自定义View时 用到Paint Canvas的一些温故 讲讲平时一些效果是怎么画的(基础篇

时间:2020-12-06 10:34:34

相关推荐

自定义View时 用到Paint Canvas的一些温故 讲讲平时一些效果是怎么画的(基础篇

转载请注明出处:王亟亟的大牛之路

上一篇把简单的一些概念理一理,还画了个圈,那这一篇讲一下图像遮盖“Xfermode”和Canvas的旋转。平移等效果

Xfermode:

AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。

PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

我们今天的呈现就是在PorterDuffXfermode 这部分实现的

PorterDuff.Mode为枚举类,一共有16个枚举值分别是

1.PorterDuff.Mode.CLEAR

所绘制不会提交到画布上。

2.PorterDuff.Mode.SRC

显示上层绘制图片

3.PorterDuff.Mode.DST

显示下层绘制图片

4.PorterDuff.Mode.SRC_OVER

正常绘制显示,上下层绘制叠盖。

5.PorterDuff.Mode.DST_OVER

上下层都显示。下层居上显示。

6.PorterDuff.Mode.SRC_IN

取两层绘制交集。显示上层。

7.PorterDuff.Mode.DST_IN

取两层绘制交集。显示下层。

8.PorterDuff.Mode.SRC_OUT

取上层绘制非交集部分。

9.PorterDuff.Mode.DST_OUT

取下层绘制非交集部分。

10.PorterDuff.Mode.SRC_ATOP

取下层非交集部分与上层交集部分

11.PorterDuff.Mode.DST_ATOP

取上层非交集部分与下层交集部分

12.PorterDuff.Mode.XOR

异或:去除两图层交集部分

13.PorterDuff.Mode.DARKEN

取两图层全部区域,交集部分颜色加深

14.PorterDuff.Mode.LIGHTEN

取两图层全部,点亮交集部分颜色

15.PorterDuff.Mode.MULTIPLY

取两图层交集部分叠加后颜色

16.PorterDuff.Mode.SCREEN

取两图层全部区域,交集部分变为透明色

在将这一系列的效果之前我们先把我们昨天画圆的例子改一下

public class TestView extends View {Paint paint;Context context;Bitmap bitmap;public TestView(Context context) {super(context);this.context = context;}public TestView(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public TestView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(getResources().getColor(R.color.SlateBlue));paint.setColor(getResources().getColor(R.color.Gold));paint.setStrokeWidth(3); //粗细paint.setAntiAlias(true); //设置画笔为无锯齿bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.bg);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("--->onDraw", "onDraw()");// canvas.drawCircle(0, 0, 90, paint);canvas.drawBitmap(bitmap,0,0,paint);canvas.drawCircle(100, 100, 90, paint);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);Log.d("--->onLayout", "changed = " + changed + " left = " + left + " top = " + top + " right = " + right + " bottom " + bottom);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);Log.d("--->onMeasure", " widthMeasureSpec =" + widthMeasureSpec + " heightMeasureSpec = " + heightMeasureSpec);setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);}}

我们在画圆之后又画了个背景图,效果如下:

在我们的圆下面有一个妹子,并且圆是会盖掉妹子那一块圆的涂抹面积的。

那我们把onDraw()方法里执行的顺序换一下呢?

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("--->onDraw", "onDraw()");// canvas.drawCircle(0, 0, 90, paint);canvas.drawCircle(100, 100, 90, paint);canvas.drawBitmap(bitmap,0,0,paint); }

如果改成这样,我们的圆就没了(效果不贴了)

利用PorterDuff.Mode就可以很好的解决这个问题当然,可能你得多绘制一次然后再做覆盖的操作了,所以在你决定先画什么后画什么之前一定理清谁在前谁在后

本来想写个大致的例子,但是想想16个都好麻烦,就拿了一个市面上比较多的图吧

Canvas静态变化

上面的代码不变,我们在新建一个Canvas然后把他里面话一点东西,来模拟我们想要的效果。

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("--->onDraw", "onDraw()");// canvas.drawCircle(0, 0, 90, paint);canvas.drawCircle(100, 100, 90, paint1);canvas.drawBitmap(bitmap, 120, 120, paint1);Canvas canvas1=new Canvas(bitmap);Paint paint2=new Paint();paint2.setColor(getResources().getColor(R.color.LightPink));paint2.setTextSize(50);canvas1.drawText("Ezreal", 0, 200, paint2);canvas1.drawText("Malzahar ",0,300,paint2);}

效果如下:

P1.我们用画布又画了2个字。那么我们来试下各种效果(分析和方法,会分两部分罗列)

平移:1.void translate(float dx, float dy)

平移参数:2个坐标点X正向右 Y正向下,负数反之。

旋转

1.void rotate(float degrees)

2.void rotate (float degrees, float px, float py)

旋转参数:以坐标原点(左上)为旋转中心转degrees度(正的为正转,负的为反转),px,py为以(px,py)为中心旋转degrees度.

缩放

1.public void scale (float sx, float sy)

2.public final void scale (float sx, float sy, float px, float py)

缩放参数:sx为水平缩放,1表示不便,大于1放大,小与1缩小(负的我没试过);sy则表示垂直,逻辑同水平.

斜切

1.void skew (float sx, float sy)

斜切参数:sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值;sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值.

P2.实现以及解释:

1.平移:

肉眼看来我们的2个字偏移了canvas1.translate(300,300);的位置,效果类似于 2个字体本身的坐标(X坐标+300,Y坐标+300)。

但是 效果是这样吗?

为了验证确实如此我们再再右侧画一个“Akali”

//并且是在平移前执行canvas1.drawText("Akali ",200,400,paint2);

然后我们在平移之后再画一个Katarina Du Couteau

并且跟平移前的阿卡丽是用以坐标

canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);

效果是卡特跟着整个坐标系走了而不是之前的坐标相加的结果。

所以:

1.每次调用canvas.drawXXXX系列函数来绘图进,都会产生一个全新的Canvas画布。

2.在Canvas与屏幕合成时,超出屏幕范围的图像是不会显示出来的。

2.旋转

我们还是回到最初的蚂蚱和EZ的样子

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("--->onDraw", "onDraw()");// canvas.drawCircle(0, 0, 90, paint);canvas.drawCircle(100, 100, 90, paint1);canvas.drawBitmap(bitmap, 120, 120, paint1);Canvas canvas1 = new Canvas(bitmap);Paint paint2 = new Paint();paint2.setColor(getResources().getColor(R.color.LightPink));paint2.setTextSize(50);// canvas1.drawText("Akali ", 200, 400, paint2);// canvas1.translate(300, 300);canvas1.drawText("Ezreal", 0, 200, paint2);canvas1.rotate(30);canvas1.drawText("Malzahar ", 0, 300, paint2);// canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);}

然后把蚂蚱旋转30度,效果如图

EZ位置没变,蚂蚱转了,并且有一部分超出了我们的妹子Bitmap所以它不见了。

然后此时此刻,我们的阿卡丽回来了,并且在蚂蚱之后

我们的啊卡里也跟着蚂蚱转走了,说明旋转和平移是一样的整个位图转走了。

如下图向着箭头方向偏了30度然后创建了一个新的Canvas

3.缩放

缩放的图我就不画了,代码就是canvas.scale(1, 1.5f); 就是Y方向缩放1.5f

也是重绘了一个Canvas和上面都一样。

4.斜切

其实也就是可以实现我们的一个斜体的效果,这里就贴一下执行效果

还有就是int save () void restore()相对比较简单,对堆栈的概念清晰的小伙伴一看就懂,不需要过多试验,这里就不明说了。

自定义View时 用到Paint Canvas的一些温故 讲讲平时一些效果是怎么画的(基础篇 二 图像遮盖 Canvas静态变化)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。