主要用到canvas.drawBitmapMesh()方法:主要接收前5个参数,后3个参数是颜色及画笔相关,可设为null
1.需要扭曲的源位图
2.图片横向分成多少个
3.图片纵向分成多少格
4.一个float[]数组,具体作用如下:
5.从第四个参数的数组中选第几个数组元素(哪个点)开始进行扭曲
所以对图片的扭曲,揉动效果,根本上是对许多点进行扭曲。
public class MainActivity extends AppCompatActivity {
private Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this , R.drawable.c));
}
class MyView extends View {
//横纵被划分为20格
private final int WIDTH = 20;
private final int HEIGHT = 20;
//共21*21个坐标点
private final int COUNT = (WIDTH + 1)*(HEIGHT + 1);
//坐标点共21*21*2 数组个数 , 因为一个坐标点有x和y所以乘以2
private final float[] verts = new float[COUNT*2];
//定义原本不变的坐标数组
private final float[] orig = new float[COUNT*2];
public MyView(Context context, int c) {
super(context);
setFocusable(true);
bitmap = BitmapFactory.decodeResource(getResources() , c);
//获取图片的宽度,高度
float bitmapwidth = bitmap.getWidth();
float bitmapheight = bitmap.getHeight();
int index = 0;
//将图片分割,然后保存21*21个坐标点
for (int y = 0 ; y <= HEIGHT ; y++){
float fy = (bitmapheight/HEIGHT) * y;
for (int x = 0 ; x <= WIDTH ; x++){
float fx = (bitmapwidth/WIDTH) * x;
//用数组保存坐标点fx , fy
orig[index*2 + 0] = verts[index*2 + 0] = fx;
orig[index*2 + 1] = verts[index*2 + 1] = fy;
index++;
}
}
setBackgroundColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
//进行扭曲,总是选定数组中第一个点开始扭曲,因为这里的处理是让数组要扭曲的点的坐标每次存到第一个元素
//该方法每次的扭曲,那之前的扭曲效果就没了
canvas.drawBitmapMesh(bitmap , WIDTH , HEIGHT , verts , 0 , null , 0 , null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
wrap(event.getX() , event.getY());
return true;
}
//计算所有的点到触摸点的距离,根据距离决定扭曲的程度
private void wrap(float cx, float cy) {
for (int i = 0 ; i < COUNT*2 ; i+=2) {
float dx = cx - orig[i + 0];
float dy = cy - orig[i + 1];
float dd = dx*dx + dy*dy;
float d = (float) Math.sqrt(dd); //所有点到触摸点的距离
//计算扭曲度。越远值越小
float pull = 100000 / (float)(dd*d);
//每次保存扭曲坐标之前,对坐标重新赋值
if (pull >= 1){ //离触摸点很近
verts[i + 0] = cx; //让参数数组的第一个元素为该点,进行扭曲,从触摸点开始扭曲
verts[i + 1] = cy;
} else {//离触摸点远了
verts[i + 0] = orig[i + 0] + dx * pull ; //在原来的点的坐标加上扭曲度,扭曲效果为向触摸点靠近
verts[i + 1] = orig[i + 1] + dy * pull ;
}
}
invalidate();
}
}
}
图中红点为触摸点