用canvas.drawBitmapMesh()扭曲图片。达到揉动图片的效果

主要用到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();
        }
    }






}

图中红点为触摸点



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值