zoukankan      html  css  js  c++  java
  • Canvas对画布及文字控制基础API学习

    这次纯API练习,比较简单,但是是为了之后的结合项目打基础的,所以也不能忽视它,下面开始:

    Canvas的平移、旋转、缩放

    这里还是以上次画那个青春痘的DEMO为例【http://www.cnblogs.com/webor2006/p/7341697.html】,在此基础上进行画步操作,先贴一下目前的代码及效果:

    /**
     * 自定义View操练----画一个形象可爱的笑脸^_^
     */
    public class MyView extends View {
    
        private Paint paint;
        /* 笑脸圆的坐标 */
        private final PointF facePoint = new PointF(240, 400);
        /* 笑脸圆的半径 */
        private final int faceRadius = 200;
    
        /* 眉毛线开始坐标 */
        private final PointF eyebrowStartPoint = new PointF(140, 250);
        /* 眉毛线结束坐标 */
        private final PointF eyebrowEndPoint = new PointF(340, 250);
    
        /* 鼻子中竖线开始坐标 */
        private final PointF noseLine1StartPoint = new PointF(240, 250);
        /* 鼻子中竖线结束坐标 */
        private final PointF noseLine1EndPoint = new PointF(240, 500);
        /* 鼻子左勾线结束坐标,其它的开始坐标为noseLine1EndPoint */
        private final PointF noseLine2EndPoint = new PointF(150, 450);
    
        /* 左眼圆的坐标 */
        private final PointF leftEyePoint = new PointF(170, 330);
        /* 右眼圆的坐标 */
        private final PointF rightEyePoint = new PointF(310, 330);
        /* 眼睛圆的半径 */
        private final int eyeRadius = 60;
    
        /* 嘴的圆弧外接矩形 */
        //参数为left(距屏幕左边的x坐标位置)、top(距屏幕左边的x坐标位置)、right(距屏幕左边的x坐标位置)、bottom(距屏幕左边的x坐标位置)
        private final RectF mouseRectF = new RectF(60, 300, 420, 550);
        /* 嘴的圆弧起始角度 */
        private final float startAngle = 380f;
        /* 嘴的圆弧的弧度 */
        private final float sweepAngle = 140f;
    
        /* 左美丽青春痘 */
        private final float[] leftAcnePoints = {130, 414, 111, 442, 152, 442, 130, 470, 130, 442};
        /* 左美丽青春痘 */
        private final float[] rightAcnePoints = {350, 414, 331, 442, 372, 442, 350, 470, 350, 442};
    
        /* 左朵耳相关的坐标点,用Path将其连接优化耳朵 */
        private final PointF leftEarMovePoint = new PointF(65, 300);
        private final PointF leftEarBezierEndPoint1 = new PointF(40, 400);
        private final PointF leftEarBezierEndPoint2 = new PointF(65, 500);
        private final PointF leftEarBezierControlPoint1 = new PointF(0, 336);
        private final PointF leftEarBezierControlPoint2 = new PointF(0, 460);
        /* 右朵耳相关的坐标点,用Path将其连接优化耳朵 */
        private final PointF rightEarMovePoint = new PointF(413, 300);
        private final PointF rightEarBezierEndPoint1 = new PointF(440, 400);
        private final PointF rightEarBezierEndPoint2 = new PointF(413, 500);
        private final PointF rightEarBezierControlPoint1 = new PointF(480, 336);
        private final PointF rightEarBezierControlPoint2 = new PointF(480, 460);
    
        public MyView(Context context) {
            this(context, null);
        }
    
        public MyView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            paint = new Paint();
            //设置画笔的颜色
            paint.setColor(Color.RED);
            //设置抗锯齿:开启它会有些性能损耗,但是画面更加平滑~
            paint.setAntiAlias(true);
            //设置画笔的样式:绘制空心图形
            paint.setStyle(Paint.Style.STROKE);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            //1、画个圆脸:
            //参数1,2:圆心的x,y坐标
            //参数3 radius:圆的半径
            canvas.drawCircle(facePoint.x, facePoint.y, faceRadius, paint);
    
            //2、画一字眉:
            //参数1,2:线的起始坐标点
            //参数3,4:线的结束坐标点
            canvas.drawLine(eyebrowStartPoint.x, eyebrowStartPoint.y, eyebrowEndPoint.x, eyebrowEndPoint.y, paint); //画一个眉毛,这里用一横线来形象的代表~~
    
            //3、画勾鼻:
            canvas.drawLine(noseLine1StartPoint.x, noseLine1StartPoint.y, noseLine1EndPoint.x, noseLine1EndPoint.y, paint); //画鼻子中竖线
            canvas.drawLine(noseLine1EndPoint.x, noseLine1EndPoint.y, noseLine2EndPoint.x, noseLine2EndPoint.y, paint); //画鼻子左勾线
    
            //4、画两眼:
            canvas.drawCircle(leftEyePoint.x, leftEyePoint.y, eyeRadius, paint);//画左眼睛,用萌萌哒的正圆来形象的代表~~
            canvas.drawCircle(rightEyePoint.x, rightEyePoint.y, eyeRadius, paint);//画右眼睛,用萌萌哒的正圆来形象的代表~~
    
            //5、画嘴:
            //参数1 RectF:矩形,是圆弧所在圆的外接矩形
            //参数2 startAngle:弧的起始角度
            //参数3 sweepAngle:弧的弧度
            //参数4 useCenter: 如果为true则会以圆中心画一个弧;如果为false则只要一个弧线,没有中心点到弧的一个连线
            canvas.drawArc(mouseRectF, startAngle, sweepAngle, false, paint);
            //for test:看一下是不是刚好圆弧就是在外切矩形里面
            //canvas.drawRect(mouseRectF, paint);
    
            //6、画美丽青春痘:
            //参数1 pts: 绘制的点的坐标集合,[x0 y0 x1 y1 x2 y2 ...]
            //参数2 offset: 参数1中的这么一串数字哪个表示X,哪个表示Y,则由此参数决定,也就是指定参数1中哪个点作为起始点作为横坐标,然后依次顺延
            //比如:如果传0,则第一个数表示x、第二个数表示y;而如果传1则第二个数是x,第三个数是y,之后的一次顺延
            //参数3 count: 需要使用集合中的几个元素
            canvas.drawPoints(leftAcnePoints, 0, leftAcnePoints.length, paint);//画左美丽青春痘
            canvas.drawPoints(rightAcnePoints, 0, rightAcnePoints.length, paint);//画右美丽青春痘
    
            //7、画耳朵方案三【利用贝塞尔曲线终极优化】:
            //利用path来优化耳朵,之前是一个太不真实的矩形代替滴
            Path leftEarPath = new Path();
            leftEarPath.moveTo(leftEarMovePoint.x, leftEarMovePoint.y);
            leftEarPath.quadTo(leftEarBezierControlPoint1.x, leftEarBezierControlPoint1.y, leftEarBezierEndPoint1.x, leftEarBezierEndPoint1.y);
            leftEarPath.quadTo(leftEarBezierControlPoint2.x, leftEarBezierControlPoint2.y, leftEarBezierEndPoint2.x, leftEarBezierEndPoint2.y);
            canvas.drawPath(leftEarPath, paint);
            Path rightEarPath = new Path();
            rightEarPath.moveTo(rightEarMovePoint.x, rightEarMovePoint.y);
            rightEarPath.quadTo(rightEarBezierControlPoint1.x, rightEarBezierControlPoint1.y, rightEarBezierEndPoint1.x, rightEarBezierEndPoint1.y);
            rightEarPath.quadTo(rightEarBezierControlPoint2.x, rightEarBezierControlPoint2.y, rightEarBezierEndPoint2.x, rightEarBezierEndPoint2.y);
            canvas.drawPath(rightEarPath, paint);
        }
    }

    记住这张笑脸的位置,下面的实验会对其进行位置变换,可以有个感观上的认识。

    ①、Canvas的平移:

    先来贴一下官网平移API的介绍:

    下面将画布的x坐标平移200,看下效果:

    编译运行:

    效果比较简单,但是需要用坐标系的概念去理解它,如下:

    ②、Canvas的旋转:

    先将①实验的代码还原,基于正脸进行旋转实验,先上官网apI介绍:

    下面实验下,将画片旋转-45度:

    编译运行:

    如何理解?还得去分析坐标系,如图:

    ③、Canvas的缩放:

    继续先将②的测试代码还原,先看一下官方API的介绍:

    下面看代码:

    编译运行:

    由于比较好理解,就不多解释,不过这里有个注意点:

    推荐写法是在做上面几个画布动作之前先调用save(),等操作处理完之后,再调用restore方法,具体如下:

    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            canvas.save();
            //平移画布
    //        canvas.translate(200, 0);
            //旋转画布
    //        canvas.rotate(-45);
            //缩放画布
            canvas.scale(0.2f, 0.2f);
    
            //1、画个圆脸:
            //参数1,2:圆心的x,y坐标
            //参数3 radius:圆的半径
            canvas.drawCircle(facePoint.x, facePoint.y, faceRadius, paint);
    
            //2、画一字眉:
            //参数1,2:线的起始坐标点
            //参数3,4:线的结束坐标点
            canvas.drawLine(eyebrowStartPoint.x, eyebrowStartPoint.y, eyebrowEndPoint.x, eyebrowEndPoint.y, paint); //画一个眉毛,这里用一横线来形象的代表~~
    
            //3、画勾鼻:
            canvas.drawLine(noseLine1StartPoint.x, noseLine1StartPoint.y, noseLine1EndPoint.x, noseLine1EndPoint.y, paint); //画鼻子中竖线
            canvas.drawLine(noseLine1EndPoint.x, noseLine1EndPoint.y, noseLine2EndPoint.x, noseLine2EndPoint.y, paint); //画鼻子左勾线
    
            //4、画两眼:
            canvas.drawCircle(leftEyePoint.x, leftEyePoint.y, eyeRadius, paint);//画左眼睛,用萌萌哒的正圆来形象的代表~~
            canvas.drawCircle(rightEyePoint.x, rightEyePoint.y, eyeRadius, paint);//画右眼睛,用萌萌哒的正圆来形象的代表~~
    
            //5、画嘴:
            //参数1 RectF:矩形,是圆弧所在圆的外接矩形
            //参数2 startAngle:弧的起始角度
            //参数3 sweepAngle:弧的弧度
            //参数4 useCenter: 如果为true则会以圆中心画一个弧;如果为false则只要一个弧线,没有中心点到弧的一个连线
            canvas.drawArc(mouseRectF, startAngle, sweepAngle, false, paint);
            //for test:看一下是不是刚好圆弧就是在外切矩形里面
            //canvas.drawRect(mouseRectF, paint);
    
            //6、画美丽青春痘:
            //参数1 pts: 绘制的点的坐标集合,[x0 y0 x1 y1 x2 y2 ...]
            //参数2 offset: 参数1中的这么一串数字哪个表示X,哪个表示Y,则由此参数决定,也就是指定参数1中哪个点作为起始点作为横坐标,然后依次顺延
            //比如:如果传0,则第一个数表示x、第二个数表示y;而如果传1则第二个数是x,第三个数是y,之后的一次顺延
            //参数3 count: 需要使用集合中的几个元素
            canvas.drawPoints(leftAcnePoints, 0, leftAcnePoints.length, paint);//画左美丽青春痘
            canvas.drawPoints(rightAcnePoints, 0, rightAcnePoints.length, paint);//画右美丽青春痘
    
            //7、画耳朵方案三【利用贝塞尔曲线终极优化】:
            //利用path来优化耳朵,之前是一个太不真实的矩形代替滴
            Path leftEarPath = new Path();
            leftEarPath.moveTo(leftEarMovePoint.x, leftEarMovePoint.y);
            leftEarPath.quadTo(leftEarBezierControlPoint1.x, leftEarBezierControlPoint1.y, leftEarBezierEndPoint1.x, leftEarBezierEndPoint1.y);
            leftEarPath.quadTo(leftEarBezierControlPoint2.x, leftEarBezierControlPoint2.y, leftEarBezierEndPoint2.x, leftEarBezierEndPoint2.y);
            canvas.drawPath(leftEarPath, paint);
            Path rightEarPath = new Path();
            rightEarPath.moveTo(rightEarMovePoint.x, rightEarMovePoint.y);
            rightEarPath.quadTo(rightEarBezierControlPoint1.x, rightEarBezierControlPoint1.y, rightEarBezierEndPoint1.x, rightEarBezierEndPoint1.y);
            rightEarPath.quadTo(rightEarBezierControlPoint2.x, rightEarBezierControlPoint2.y, rightEarBezierEndPoint2.x, rightEarBezierEndPoint2.y);
            canvas.drawPath(rightEarPath, paint);
    
            canvas.restore();
        }

    绘制文本

    这里用一个新的工程来实验,其代码结构比较简单,一个Activity,一个自定义的view:

    ①、绘制文本:

    先看一下官方API:

    比较好理解:

    编译运行:

    但是字体有点小,于是乎看②

    ②、设置文本大小:

    太小儿科上,直接上代码,不解释:

    编译运行:

    ③、设置文本粗体:

    ④、设置文本下划线:

    编译运行:

    ⑤、设置文本中划线:

    ⑥、设置文本对齐方式:

    这个有必要解释一下,先看下官网API:

    其中有三种对齐方式:

    下面先上代码看结果:

    居中对齐:

    编译运行:

    左对齐:

    编译运行:

    右对齐:

    编译运行:

    呃~~发现问题木有,居然向左对齐文字在屏幕偏右,而向右对齐文字在屏幕偏右,这是为啥呢,下面解释一下:

    而对齐方式就是依据上面的基准点来的,规则如下:

    居中对齐,则是基准点位于文本的中间;

    居右对齐,则是基准点位于文本的右边;

    居左对齐,则是基准点位于文本的左边;

    ⑦、设置文本x方向缩放:

    先看一下官网API:

    下面看下代码效果:

    编译运行:

    也就是X横向扩宽了2倍,但是木有对Y进行扩宽的api。

  • 相关阅读:
    我的航拍直升机 控制基站软件的编写历程(2.2)——Qt Creator 版本控制系统
    windows下QT开发环境建立方法
    QT 4.5 windows版本 安装问题 及 Junction 使用
    各种平台下编译qt工程
    华为面试题
    strcpy,strncpy,strlcpy,memcpy
    QT/E 更换字体问题
    Linux设备驱动编程中断处理
    oracle数据库连接池的使用
    Windows下QT的安装
  • 原文地址:https://www.cnblogs.com/webor2006/p/7400259.html
Copyright © 2011-2022 走看看