图形绘制详解(5)——蒙版实例和加速球实例
前面我们做了一个示例是处理两个交叠的图形,这里我们在哪个例子的基础上继续来做一些图形特效的例子。
范例1:蒙版效果
功能:
底层放一张图片,上层一张蒙版,通过点击,显示底层图片
思路:
使用两张图片重叠后,中间透明的方式,使每次点击蒙版,使透明显示出底层图片。
效果图:
总代码:
public class MyBitmapView2 extends View{
private int width;
private int height;
private Bitmap bitmap;
private Canvas canvasBit;
private Paint paintCircle;
private Paint paintRect;
private Paint paint;
private int bimapWidth;
private int bitmapHeight;
private Bitmap bitmapBack;
private Path pathAlph;
private float x;
private float y;
private Paint paintAlph;
public MyBitmapView2(Context context) {
super(context);
}
public MyBitmapView2(Context context, AttributeSet attrs) {
super(context, attrs);
paintCircle = new Paint();
paintCircle.setColor(Color.YELLOW);
paintRect = new Paint();
paintRect.setColor(Color.GREEN);
paint = new Paint();
//使重叠部分不显示
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//必须设置在上面的控件
paintRect.setXfermode(mode);
//透明圆
pathAlph = new Path();
paintAlph = new Paint();
paintAlph.setAlpha(100);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
bitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);//创建一个bitmap
canvasBit=new Canvas(bitmap);//创建一个包含上面bitmap的canvas
bitmapBack=BitmapFactory.decodeResource(getResources(), R.mipmap.yangmi3);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画上背景图片,且放大
canvas.drawBitmap(bitmapBack,
new Rect(0, 0, bitmapBack.getWidth(), bitmapBack.getHeight()),
new Rect(0, 0, width, height), paint);
// canvas.drawColor(Color.RED);//将画布背景布成红色
//canvasBit.drawCircle(width / 2, height / 2, width / 2, paintCircle);//通过bitmap的canvas画
canvasBit.drawRect(0, 0, width, height, paintCircle);//蒙版
canvasBit.drawPath(pathAlph,paintRect);//注意用paintRect画笔来做,因为他俩重叠的部分会变透明
canvas.drawBitmap(bitmap,0,0,paint);//最后将bitmap添加到最后的画布中
}
//ontouch事件
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
x = event.getX();//注意:获得的是event事件的位置
y = event.getY();
//设置一个圆的路径,这样,在onDraw中使用路径,只要不reset,点击了圆就保留。
pathAlph.addCircle(x,y,50, Path.Direction.CW);
invalidate();;//刷新
return true;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
代码分析:
1)图层叠放顺序:从底层到上层分别是:照片,蒙版,点击圆。注意透明特效要加到上层的点击的图层上。
注意第一步张使用的图片放大的方法,是将图片的一块区域放到现在画布的指定区域。这里直接将图片所有区域放到整个画布中填充达到放大的效果。
特效:
2)ontouch事件:
注意在touch事件中:
第二步:是为了保证,点击下一次时,上次效果还存在,使用path只要不reset,这样效果就一直在。
第三步的刷新界面一定不要落下啊,否则点击是没有反应的,我就吃过亏啊。
第四步一定要返回true,否则就会出错。
范例2:范例1的延伸功能:
功能:滑动刮刮乐效果,并点击时保存位图。
先来看一下效果:(达到圆滑笔触效果)
不错吧,像刮刮乐的效果,下面来看看这种效果是如何实现的吧:
1.画笔的属性设置:
关注这两行代码,设置头部和拉线中间的样式:
paintRect.setStrokeJoin(Paint.Join.ROUND);//头部样式
paintRect.setStrokeCap(Paint.Cap.ROUND);//划线中间样式
2.onTouch事件:
利用贝塞尔每次拉线到(x,y)后,要将此位置设为oldposition,然后继续拉线。
3.活动中点击按钮保存:
保存前:
bitView.setDrawingCacheEnabled(true);//设置自定义的view
Bitmap bit = bitView.getDrawingCache(true);//获取bitmap
保存:
bit.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
API中的介绍:
4.加”写”权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
这样一个类似刮刮乐的效果就做好了,你学会了么^^
范例3:实现加速球效果:
功能:实现小球内水流模拟。
效果演示:
这里的水面是从底部上升到顶的哟,而且,数字显示百分比。是不是很炫,这样是不是和加速球很像,现在我们就来看看如何做出这样效果的吧。(这是在前面曲线效果的例子的基础上做的哟^^)
自定义的view:
package com.example.day0916.widget;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.day0916.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class MyBitmapActivity2 extends Activity {
private Button mButtonSave;
private MyTBitmapView bitView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_bitmap_activity2);
mButtonSave = (Button) findViewById(R.id.buttonSave);
bitView = (MyTBitmapView) findViewById(R.id.bitmapSave);
mButtonSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bitView.setDrawingCacheEnabled(true);
Bitmap bit = bitView.getDrawingCache(true);
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
Log.d("message",Environment.getExternalStorageDirectory()+"+"+System.currentTimeMillis());
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {//注意写到上面file不存在的外面
bit.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
});
}
}
代码分析:
总思路:这里利用的是红色的圆和下面绿色的路径之间交叠部分显露的特效做出来的。即下图圈出了的效果
交叠部分代码:
//设置特效
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);//必须设置在上面的控件
paintPath.setXfermode(mode);
绿色路径代码:
Handler来控制曲线的流动和高度的变化: