欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中利用matrix 控制图片的旋转、缩放、移动

程序员文章站 2023-11-29 22:53:58
本文主要讲解利用android中matrix控制图形的旋转缩放移动,具体参见一下代码:复制代码 代码如下:/**  * 使用矩阵控制图片移动、缩放、旋转 &nbs...
本文主要讲解利用android中matrix控制图形的旋转缩放移动,具体参见一下代码:
复制代码 代码如下:

/**
 * 使用矩阵控制图片移动、缩放、旋转
 */ 
public class commonimgeffectview extends view { 

    private context context ; 
    private bitmap mainbmp , controlbmp ; 
    private int mainbmpwidth , mainbmpheight , controlbmpwidth , controlbmpheight ; 
    private matrix matrix ;  
    private float [] srcps , dstps ; 
    private rectf srcrect , dstrect ; 
    private paint paint ,paintrect , paintframe; 
    private float deltax = 0, deltay = 0; //位移值 
    private float scalevalue = 1; //缩放值 
    private point lastpoint ; 
    private point prepivot , lastpivot; 
    private float predegree , lastdegree ; 
    private short currentselectedpointindex;        //当前操作点击点 
    private point symmetricpoint  = new point();    //当前操作点对称点 

    /**
     * 图片操作类型
     */ 
    public static final int oper_default = -1;      //默认 
    public static final int oper_translate = 0;     //移动 
    public static final int oper_scale = 1;         //缩放 
    public static final int oper_rotate = 2;        //旋转 
    public static final int oper_selected = 3;      //选择 
    public int lastoper = oper_default; 

    /* 图片控制点
     * 0---1---2
     * |       |
     * 7   8   3
     * |       |
     * 6---5---4 
     */ 
    public static final int ctr_none = -1; 
    public static final int ctr_left_top = 0; 
    public static final int ctr_mid_top = 1; 
    public static final int ctr_right_top = 2; 
    public static final int ctr_right_mid = 3; 
    public static final int ctr_right_bottom = 4; 
    public static final int ctr_mid_bottom = 5; 
    public static final int ctr_left_bottom = 6; 
    public static final int ctr_left_mid = 7; 
    public static final int ctr_mid_mid = 8; 
    public int current_ctr = ctr_none; 

    public commonimgeffectview(context context){ 
        super(context); 
        this.context = context ; 
    } 

    public commonimgeffectview(context context, attributeset attrs) { 
        super(context, attrs); 
        this.context = context ; 
        initdata(); 
    } 

    /**
     * 初始化数据
     * @author 张进
     */ 
    private void initdata(){ 
        mainbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.flower); 
        controlbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.control); 
        mainbmpwidth = mainbmp.getwidth(); 
        mainbmpheight = mainbmp.getheight(); 
        controlbmpwidth = controlbmp.getwidth(); 
        controlbmpheight = controlbmp.getheight(); 

        srcps = new float[]{ 
                                0,0,  
                                mainbmpwidth/2,0,  
                                mainbmpwidth,0,  
                                mainbmpwidth,mainbmpheight/2, 
                                mainbmpwidth,mainbmpheight,  
                                mainbmpwidth/2,mainbmpheight,  
                                0,mainbmpheight,  
                                0,mainbmpheight/2,  
                                mainbmpwidth/2,mainbmpheight/2 
                            }; 
        dstps = srcps.clone(); 
        srcrect = new rectf(0, 0, mainbmpwidth, mainbmpheight); 
        dstrect = new rectf(); 

        matrix = new matrix(); 

        prepivot = new point(mainbmpwidth/2, mainbmpheight/2); 
        lastpivot = new point(mainbmpwidth/2, mainbmpheight/2); 

        lastpoint = new point(0,0); 

        paint = new paint(); 

        paintrect = new paint(); 
        paintrect.setcolor(color.red); 
        paintrect.setalpha(100); 
        paintrect.setantialias(true); 

        paintframe = new paint(); 
        paintframe.setcolor(color.green); 
        paintframe.setantialias(true); 

        setmatrix(oper_default); 
    } 

    /**
     * 矩阵变换,达到图形平移的目的
     * @author 张进
     */ 
    private void setmatrix(int operationtype){ 
        switch (operationtype) { 
        case oper_translate: 
            matrix.posttranslate(deltax , deltay); 
            break; 
        case oper_scale: 
            matrix.postscale(scalevalue, scalevalue, symmetricpoint.x, symmetricpoint.y); 
            break; 
        case oper_rotate: 
            matrix.postrotate(predegree - lastdegree, dstps[ctr_mid_mid * 2], dstps[ctr_mid_mid * 2 + 1]); 
            break; 
        } 

        matrix.mappoints(dstps, srcps); 
        matrix.maprect(dstrect, srcrect); 
    } 

    private boolean isonpic(int x , int y){ 
        if(dstrect.contains(x, y)){ 
            return true; 
        }else  
            return false; 
    } 

    private int getoperationtype(motionevent event){ 

        int evx = (int)event.getx(); 
        int evy = (int)event.gety(); 
        int curoper = lastoper; 
        switch(event.getaction()) { 
            case motionevent.action_down: 
                current_ctr = isoncp(evx, evy); 
                log.i("img", "current_ctr is "+current_ctr); 
                if(current_ctr != ctr_none || isonpic(evx, evy)){ 
                    curoper = oper_selected; 
                } 
                break; 
            case motionevent.action_move: 
                    if(current_ctr > ctr_none && current_ctr < ctr_mid_mid ){ 
                        curoper = oper_scale; 
                    }else if(current_ctr == ctr_mid_mid ){ 
                        curoper = oper_rotate; 
                    }else if(lastoper == oper_selected){ 
                        curoper = oper_translate; 
                    } 
                break; 
            case motionevent.action_up: 
                curoper = oper_selected; 
                break; 
            default: 
                break; 
        } 
        log.d("img", "curoper is "+curoper); 
        return curoper; 

    } 

     /**
     * 判断点所在的控制点
     * @param evx
     * @param evy
     * @return
     */  
    private int isoncp(int evx, int evy) { 
        rect rect = new rect(evx-controlbmpwidth/2,evy-controlbmpheight/2,evx+controlbmpwidth/2,evy+controlbmpheight/2); 
        int res = 0 ; 
        for (int i = 0; i < dstps.length; i+=2) { 
            if(rect.contains((int)dstps[i], (int)dstps[i+1])){ 
                return res ; 
            } 
            ++res ;  
        } 
        return ctr_none; 
    } 

     

    @override 
    public boolean dispatchtouchevent(motionevent event) { 
        int evx = (int)event.getx(); 
        int evy = (int)event.gety(); 

        int opertype = oper_default; 
        opertype = getoperationtype(event); 

        switch (opertype) { 
        case oper_translate: 
            translate(evx, evy); 
            break; 
        case oper_scale: 
            scale(event); 
            break; 
        case oper_rotate: 
            rotate(event); 
            break; 
        } 

        lastpoint.x = evx; 
        lastpoint.y = evy;   

        lastoper = opertype; 
        invalidate();//重绘 
        return true; 
    } 

    /**
     * 移动
     * @param evx
     * @param evy
     * @author zhang_jin1
     */ 
    private void translate(int evx , int evy){ 

        prepivot.x += evx - lastpoint.x; 
        prepivot.y += evy -lastpoint.y; 

        deltax = prepivot.x - lastpivot.x; 
        deltay = prepivot.y - lastpivot.y; 

        lastpivot.x = prepivot.x; 
        lastpivot.y = prepivot.y; 

        setmatrix(oper_translate); //设置矩阵 

    } 

    /**
     * 缩放
     * 0---1---2
     * |       |
     * 7   8   3
     * |       |
     * 6---5---4
     * @param evx
     * @param evy
     */ 
    private void scale(motionevent event) { 

        int pointindex = current_ctr*2 ; 

        float px = dstps[pointindex]; 
        float py = dstps[pointindex+1]; 

        float evx = event.getx(); 
        float evy = event.gety(); 

        float oppositex = 0 ; 
        float oppositey = 0 ; 
        if(current_ctr<4 && current_ctr >= 0){ 
             oppositex = dstps[pointindex+8]; 
             oppositey = dstps[pointindex+9]; 
        }else if(current_ctr >= 4){ 
             oppositex = dstps[pointindex-8]; 
             oppositey = dstps[pointindex-7]; 
        } 
        float temp1 = getdistanceoftwopoints(px,py,oppositex,oppositey); 
        float temp2 = getdistanceoftwopoints(evx,evy,oppositex,oppositey); 

        this.scalevalue = temp2 / temp1 ; 
        symmetricpoint.x = (int) oppositex; 
        symmetricpoint.y = (int)oppositey; 

        log.i("img", "scalevalue is "+scalevalue); 
        setmatrix(oper_scale); 
    } 

    /**
     * 旋转图片
     * 0---1---2
     * |       |
     * 7   8   3
     * |       |
     * 6---5---4 
     * @param evx
     * @param evy
     */ 
    private void rotate(motionevent event) { 

        if(event.getpointercount() == 2){ 
            predegree = computedegree(new point((int)event.getx(0), (int)event.gety(0)), new point((int)event.getx(1), (int)event.gety(1))); 
        }else{ 
            predegree = computedegree(new point((int)event.getx(), (int)event.gety()), new point((int)dstps[16], (int)dstps[17])); 
        } 
        setmatrix(oper_rotate); 
        lastdegree = predegree; 
    } 

     
    /**
     * 计算两点与垂直方向夹角
     * @param p1
     * @param p2
     * @return
     */ 
    public float computedegree(point p1, point p2){ 
        float tran_x = p1.x - p2.x; 
        float tran_y = p1.y - p2.y; 
        float degree = 0.0f; 
        float angle = (float)(math.asin(tran_x/math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/math.pi); 
        if(!float.isnan(angle)){ 
            if(tran_x >= 0 && tran_y <= 0){//第一象限 
                degree = angle; 
            }else if(tran_x <= 0 && tran_y <= 0){//第二象限 
                degree = angle; 
            }else if(tran_x <= 0 && tran_y >= 0){//第三象限 
                degree = -180 - angle; 
            }else if(tran_x >= 0 && tran_y >= 0){//第四象限 
                degree = 180 - angle; 
            } 
        } 
        return degree; 
    } 

    /**
     * 计算两个点之间的距离
     * @param p1
     * @param p2
     * @return
     */ 
    private float getdistanceoftwopoints(point p1, point p2){ 
        return (float)(math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); 
    } 

    private float getdistanceoftwopoints(float x1,float y1,float x2,float y2){ 
        return (float)(math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); 
    } 

     
    @override 
    public void ondraw(canvas canvas){ 
        drawbackground(canvas);//绘制背景,以便测试矩形的映射 
        canvas.drawbitmap(mainbmp, matrix, paint);//绘制主图片 
        drawframe(canvas);//绘制边框,以便测试点的映射 
        drawcontrolpoints(canvas);//绘制控制点图片 
    } 

    private void drawbackground(canvas canvas){ 
        canvas.drawrect(dstrect, paintrect); 
    } 

    private void drawframe(canvas canvas){ 
        canvas.drawline(dstps[0], dstps[1], dstps[4], dstps[5], paintframe); 
        canvas.drawline(dstps[4], dstps[5], dstps[8], dstps[9], paintframe); 
        canvas.drawline(dstps[8], dstps[9], dstps[12], dstps[13], paintframe); 
        canvas.drawline(dstps[0], dstps[1], dstps[12], dstps[13], paintframe); 
        canvas.drawpoint(dstps[16], dstps[17], paintframe); 
    } 

    private void drawcontrolpoints(canvas canvas){ 

        for (int i = 0; i < dstps.length; i+=2) { 
            canvas.drawbitmap(controlbmp, dstps[i]-controlbmpwidth/2, dstps[i+1]-controlbmpheight/2, paint); 
        } 

    } 



demo效果:

Android中利用matrix 控制图片的旋转、缩放、移动

Android中利用matrix 控制图片的旋转、缩放、移动

Android中利用matrix 控制图片的旋转、缩放、移动

Android中利用matrix 控制图片的旋转、缩放、移动