zoukankan      html  css  js  c++  java
  • 自定义控件详解(三):Canvas效果变换

    Canvas 画布

    从前面我们已经知道了 Canvas 类可以绘出 各种形状。

    这里学习一下Canvas 类的变换效果(平移,旋转等)

    首先需要了解一下Canvas 画布, 我们用Canvas.DrawXXX()方法的时候并不是在一张画布上进行绘制。而是每次调用.DrawXXX()方法,都会生成一个新的画布并在上面绘制,这就类似于PS中的图层

    从下面会看到解释。

    一、偏移(.translate)

          即让画布平移,之后上面的绘制操作也会跟着平移

    public void translate(float dx, float dy) ; //画布偏移
    float
    dx:水平方向平移的距离,正数指向正方向(向右)平移的量,负数为向负方向(向左)平移的量 flaot dy:垂直方向平移的距离,正数指向正方向(向下)平移的量,负数为向负方向(向上)平移的量
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(2);
    
            //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
            canvas.drawRect(100,100,400,300,paint);
    
            //对画布进行平移操作
            canvas.translate(120,120);
            paint.setColor(Color.BLACK);
    
            //绘制一个宽300 高200 的矩形 ,因为画布向右平移了120px,向下平移了120px,
            // 所以这时距屏幕左上角的距离为(100+120,100+120)
            canvas.drawRect(100,100,400,300,paint);    

       从下可见绿色框的是平移(100,100)后的新画布的位置,多出界面的部分不再显示

       黑色的矩形是在新的画布位置(绿色框)左上角为原点,(100,100)位置绘制的

      

      

      注意这时候,每次drawXXX 绘制的画布位置都以新的画布为准,比如我再绘制一个矩形

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(2);
    
            //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
            canvas.drawRect(100,100,400,300,paint);
    
            //对画布进行平移操作
            canvas.translate(120,120);
            paint.setColor(Color.BLACK);
    
            //绘制一个宽300 高200 的矩形 ,因为画布向右平移了120px,向下平移了120px,
            // 所以这时距屏幕左上角的距离为(100+120,100+120)
            canvas.drawRect(100,100,400,300,paint);
            
            //再绘制一个蓝色的矩形 ,看看这个矩形是以平移前的画布左上角为原点还是以平移后的画布左上角为原点
            paint.setColor(Color.BLUE);
            canvas.drawRect(200,200,500,400,paint); 

     

     

      可见当画布进行转换(平移、旋转等)操作之后,往后drawXXX的时候都以新的画布位置为准  

      那么,比如我只想让第二个矩形所在的画布平移,而往后的都是以原来的画布为准,怎么办,难道还需要逆向操作,怎么平移出去的再怎么平移回来么

      其实Canvas类还有 两个方法:

    canvas.save();        //把画布的状态(位置等)保存到栈中
    
    canvas.restore();   //把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布

     举例:

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(2);
    
            //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
            canvas.drawRect(100,100,400,300,paint);
            canvas.save(); //保存当前画布状态
    
            //对画布进行平移操作
            canvas.translate(120,120);
            paint.setColor(Color.BLACK);
    
            //绘制一个宽300 高200 的矩形 ,因为画布向右平移了120px,向下平移了120px,
            // 所以这时距屏幕左上角的距离为(100+120,100+120)
            canvas.drawRect(100,100,400,300,paint);
    
            canvas.restore(); //恢复成栈顶保存的画布状态
            //再绘制一个蓝色的矩形 ,看看这个矩形是以平移前的画布左上角为原点还是以平移后的画布左上角为原点
            paint.setColor(Color.BLUE);
            canvas.drawRect(200,200,500,400,paint);

    可以看到,红色矩形是在原始画布上绘制的,然后保存原始画布的状态,

         将画布平移(100,100) 绘制一个黑色的矩形,绘制之后将画布状态恢复到栈顶保存的状态

           这时候再绘制一个蓝色的矩形,会发现这个蓝色矩形是在原状态画布上绘制的。

    二、旋转(.rotate)

    public void rotate(float degrees)
    public void rotate (float degrees, float px, float py)

    第一个构造函数直接输入旋转的度数,正数是顺时针旋转,负数指逆时针旋转,它的旋转中心点是原点(0,0)
    第二个构造函数除了度数以外,还可以指定旋转的中心点坐标(px,py)

     

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(2);
    
            //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
            canvas.drawRect(200,200,400,300,paint);
    
            //对画布进行旋转操作
            canvas.rotate(15);  // 控制旋转的角度,顺时针
            paint.setColor(Color.BLACK);
    
            //绘制一个宽300 高200 的矩形 ,因为画布向右平移了120px,向下平移了120px,
            // 所以这时距屏幕左上角的距离为(100+120,100+120)
            canvas.drawRect(200,200,400,300,paint);

     

     三、缩放(.scale)

    public void scale (float sx, float sy) 
    sx : 水平缩放的程度   
    sy : 垂直缩放的程度

    单位float, >1 表示扩大, <1 表示缩小 =1表示不变化
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.RED);
    paint.setStrokeWidth(2);

    //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
    canvas.drawRect(0,0,400,300,paint);

    //对画布进行缩放操作
    canvas.scale(0.5f,0.5f); //缩小一半
    paint.setColor(Color.BLACK);

    //绘制一个宽300 高200 的矩形 ,因为画布向右平移了120px,向下平移了120px,
    // 所以这时距屏幕左上角的距离为(100+120,100+120)
    canvas.drawRect(0,0,400,300,paint);

    四、倾斜(.skew)

    public void skew (float sx, float sy)
    float sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值,
    float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值,

    注意:倾斜角度的tan值,比如倾斜60度,tan60=根号3,小数对应1.732,那么参数就是1.732

     Paint paint = new Paint();
     paint.setStyle(Paint.Style.FILL);
     paint.setColor(Color.RED);
     paint.setStrokeWidth(2);
    
     //先绘制一个 左上角坐标(100,100) 宽300 高200 的矩形
     canvas.drawRect(0,0,400,300,paint);
     //对画布进行缩放操作
     canvas.skew(1.732f,0);  //缩小一半
     paint.setColor(Color.BLACK);
     canvas.drawRect(0,0,400,300,paint);

      

        

  • 相关阅读:
    设计模式(十)外观模式
    设计模式(九)装饰器模式
    设计模式(八)组合模式
    设计模式(七)桥接模式
    设计模式(六)代理模式
    设计模式(五)适配器模式
    linux 安装 node
    LeetCode 335. Self Crossing
    LeetCode 332. Reconstruct Itinerary 最小欧拉路径
    LeetCode 327. Count of Range Sum 区间和的个数
  • 原文地址:https://www.cnblogs.com/xqxacm/p/6667739.html
Copyright © 2011-2022 走看看