——在vue中大家能够给input控件2个ref属性,带大家来一步一步深远自定义View的世界

咱们跟着唠

亿万先生官方网站 1

1.先是次用控件获取一张图片,我们看出控件获取到了数额

OK,那就从头动工吧。

let canvasCtx = canvas.getContext('2d')

1.预备干活

先是,要贯彻这些时钟,作者得继续自View来自身绘制时钟,因为那种功能没有主意继续已有控件去完善效率。然后大家来看看大家那边须求什么变量?在那篇博客中自作者暂时不打算介绍自定义属性以及View的度量,那里作者只想介绍绘图API,所以View的轻重缓急以及钟表表针的颜料等本身都暂时先给二个固定的值。OK,那么大家须要的变量主要就是底下多少个:

/**
     * 绘制表盘的画笔
     */
    private Paint circlePaint;

    /**
     * 绘制表盘数字
     */
    private Paint numPaint;
    /**
     * 绘制表心
     */
    private Paint dotPaint;
    /**
     * 时针
     */
    private Paint hourPaint;
    /**
     * 分针
     */
    private Paint minutePaint;
    /**
     * 秒针
     */
    private Paint secondPaint;
    /**
     * View宽度,默认256dp
     */
    private int width;
    /**
     * View高度,默认256dp
     */
    private int height;
    /**
     * 日历类,用来获取当前时间
     */
    private Calendar calendar;
    /**
     * 当前时针颜色
     */
    private int hourColor;
    /**
     * 当前分针颜色
     */
    private int minuteColor;
    /**
     * 当前秒针颜色
     */
    private int secondColor;
    /**
     * 时针宽度
     */
    private int hourWidth;
    /**
     * 分针宽度
     */
    private int minuteWidth;
    /**
     * 秒针宽度
     */
    private int secondWidth;

总共便是这么八个变量。

请看那里

4.制图钟表

地方装有的劳作做完之后,接下去就是绘制钟表了,绘制工作大家身处了onDraw方法中实行,在自定义控件时,倘若该控件是我们后续自View来兑现的,那么基本上这几个控件正是亟需大家和好来绘制了。

OK,那我们来看看钟表的绘图吧。

钟表不算复杂,不过我们也须求一步一步来:

率先是绘制表盘,那个最简便易行:

        //1.圆心X轴坐标,2.圆心Y轴坐标,3.半径,4.画笔
        int radius = width / 2 - 10;
        //画表盘
        canvas.drawCircle(width / 2, height / 2, radius, circlePaint);

radius表示表盘的半径,通过drawCircle绘制多个圆环,四个参数分别是圆环的中坚点坐标,圆环的半径以及绘制圆环的画笔。

圆环画好未来,那么接下去就是绘制表心了,也正是表面正着力十一分浅莲红的圆心。

canvas.drawCircle(width / 2, height / 2, 15, dotPaint);

一点也不细略吗。

OK,多少个最简便的东东画完事后,那么接下去便是绘制表盘的岁月刻度了,时间刻度的绘图除了数字之外,还有三个法国红的短线,大家一起要画十三个那种东西,那么那么些要怎么绘制呢?思路有广大,你可以依据高级中学的数学知识,计算出每1个数字的坐标以及每三个短线初叶地方和终止地方的坐标,然后绘制出来,毫无疑问,那种办法的计算量太大,那我们那里运用一个简练的法子:小编老是只在十二点的卓殊地点上进行绘图,就算急需绘制一点,那么本人把画布逆时针转动30度到十二点的地方,然后画上1和叁个短线之后再将画布顺时针旋转30度,假诺是绘制2点,那么小编把画布逆时针转动60度到十二点的岗位,然后绘制上2和二个短线,绘制完结以往再将画布顺时针旋转60度,思路正是这么,下边大家来探视代码:

        for (int i = 1; i < 13; i++) {
            //在旋转之前保存画布状态
            canvas.save();
            canvas.rotate(i * 30, width / 2, height / 2);
            //1.2表示起点坐标,3.4表示终点坐标,5.画笔
            canvas.drawLine(width / 2, height / 2 - radius, width / 2, height / 2 - radius + 10, circlePaint);
            //画表盘数字1.要绘制的文本,2.文本x轴坐标,3.文本基线,4.文本画笔
            canvas.drawText(i + "", width / 2, height / 2 - radius + 22, numPaint);
            //恢复画布状态
            canvas.restore();
        }

自己用一个循环来绘制那十二个刻度,在历次旋转画布以前,小编都通过2个canvas.save()方法来保存画布当前的情状,保存之后再对画布实行旋转操作,旋转达成以往正是画线画数字,那几个都很简单,在绘制达成现在,笔者索要调用canvas的restore()方法,该情势能够让画布复苏到旋转从前的角度。一般景况下,canvas.save()方法和canvas.restore()方法都是成对出现的,那一点大家要小心。

OK,那一个事物都绘制实现今后,接下去就该绘制表针了,表针的绘图思路和方面一样,也是先旋转表盘,然后绘制表针,绘制完成之后,再把表盘旋转回从前的事态。那里自身就不再详细表明了,大家看代码:

        //获得当前小时
        int hour = calendar.get(Calendar.HOUR);
        canvas.save();
        //旋转屏幕
        canvas.rotate(hour * 30, width / 2, height / 2);
        //画时针
        canvas.drawLine(width / 2, height / 2 + 20, width / 2, height / 2 - 90, hourPaint);
        canvas.restore();

        int minute = calendar.get(Calendar.MINUTE);
        canvas.save();
        canvas.rotate(minute * 6, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 + 30, width / 2, height / 2 - 110, minutePaint);
        canvas.restore();
        int second = calendar.get(Calendar.SECOND);
        canvas.save();
        canvas.rotate(second * 6, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 + 40, width / 2, height / 2 - 130, secondPaint);
        canvas.restore();

OK,全体的业务做完事后,我们得以在布局文件中添加如下代码,来查阅我们的做事做得怎么着:

    <org.mobiletrain.clockview.ClockView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

添加实现之后,运维,不出意外的话,你的App上应当已经体现了二个时钟了,不过这么些时钟是板上钉钉的,那么大家该怎么让时钟动起来呢?其实很简答,大家只需求每隔一秒重新获得calendar实例,然后重绘钟表即可,所以,在onDraw方法的先河和终止,大家还要分别拉长如下两行代码:

1.初始处添加:

calendar = Calendar.getInstance();

那行代码用来得到最新的日子的实例

2.了事处添加:

postInvalidateDelayed(1000);

那行代码用来重绘钟表,可是重绘是在1秒今后。

OK,至此,我们的自定义钟表就到位了,完整的代码应该是其一样子:

/**
 * Created by wangsong on 2016/3/29.
 */
public class ClockView extends View {

    /**
     * 绘制表盘的画笔
     */
    private Paint circlePaint;

    /**
     * 绘制表盘数字
     */
    private Paint numPaint;
    /**
     * 绘制表心
     */
    private Paint dotPaint;
    /**
     * 时针
     */
    private Paint hourPaint;
    /**
     * 分针
     */
    private Paint minutePaint;
    /**
     * 秒针
     */
    private Paint secondPaint;
    /**
     * View宽度,默认256dp
     */
    private int width;
    /**
     * View高度,默认256dp
     */
    private int height;
    /**
     * 日历类,用来获取当前时间
     */
    private Calendar calendar;
    /**
     * 当前时针颜色
     */
    private int hourColor;
    /**
     * 当前分针颜色
     */
    private int minuteColor;
    /**
     * 当前秒针颜色
     */
    private int secondColor;
    /**
     * 时针宽度
     */
    private int hourWidth;
    /**
     * 分针宽度
     */
    private int minuteWidth;
    /**
     * 秒针宽度
     */
    private int secondWidth;

    //在代码中创建控件时调用
    public ClockView(Context context) {
        this(context, null);
    }

    //在布局文件中创建View时调用
    public ClockView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        //获取当前时间的实例
        calendar = Calendar.getInstance();
        //时钟默认宽高
        width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 256, getResources().getDisplayMetrics());
        height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 256, getResources().getDisplayMetrics());
        //初始化表针的颜色
        hourColor = Color.RED;
        minuteColor = Color.GREEN;
        secondColor = Color.BLUE;
        //初始化表针的宽度
        hourWidth = 8;
        minuteWidth = 5;
        secondWidth = 2;
        //初始化各种画笔
        circlePaint = new Paint();
        //去锯齿
        circlePaint.setAntiAlias(true);
        //设置画笔颜色
        circlePaint.setColor(Color.GREEN);
        //设置画笔style为描边
        circlePaint.setStyle(Paint.Style.STROKE);
        //设置描边的宽度
        circlePaint.setStrokeWidth(6);
        dotPaint = new Paint();
        dotPaint.setAntiAlias(true);
        dotPaint.setColor(Color.RED);
        dotPaint.setStyle(Paint.Style.FILL);
        numPaint = new Paint();
        numPaint.setColor(Color.RED);
        numPaint.setAntiAlias(true);
        //文本对齐方式
        numPaint.setTextAlign(Paint.Align.CENTER);
        hourPaint = new Paint();

        hourPaint.setColor(hourColor);
        hourPaint.setStyle(Paint.Style.FILL);
        hourPaint.setStrokeWidth(hourWidth);
        minutePaint = new Paint();
        minutePaint.setColor(minuteColor);
        minutePaint.setStyle(Paint.Style.FILL);
        minutePaint.setStrokeWidth(minuteWidth);
        secondPaint = new Paint();
        secondPaint.setColor(secondColor);
        secondPaint.setStyle(Paint.Style.FILL);
        secondPaint.setStrokeWidth(secondWidth);
    }

    //绘制View
    @Override
    protected void onDraw(Canvas canvas) {
        calendar = Calendar.getInstance();
        //1.圆心X轴坐标,2.圆心Y轴坐标,3.半径,4.画笔
        int radius = width / 2 - 10;
        //画表盘
        canvas.drawCircle(width / 2, height / 2, radius, circlePaint);

        canvas.drawCircle(width / 2, height / 2, 15, dotPaint);
        for (int i = 1; i < 13; i++) {
            //在旋转之前保存画布状态
            canvas.save();
            canvas.rotate(i * 30, width / 2, height / 2);
            //1.2表示起点坐标,3.4表示终点坐标,5.画笔
            canvas.drawLine(width / 2, height / 2 - radius, width / 2, height / 2 - radius + 10, circlePaint);
            //画表盘数字1.要绘制的文本,2.文本x轴坐标,3.文本基线,4.文本画笔
            canvas.drawText(i + "", width / 2, height / 2 - radius + 22, numPaint);
            //恢复画布状态
            canvas.restore();
        }
        //获得当前小时
        int hour = calendar.get(Calendar.HOUR);
        canvas.save();
        //旋转屏幕
        canvas.rotate(hour * 30, width / 2, height / 2);
        //画时针
        canvas.drawLine(width / 2, height / 2 + 20, width / 2, height / 2 - 90, hourPaint);
        canvas.restore();

        int minute = calendar.get(Calendar.MINUTE);
        canvas.save();
        canvas.rotate(minute * 6, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 + 30, width / 2, height / 2 - 110, minutePaint);
        canvas.restore();
        int second = calendar.get(Calendar.SECOND);
        canvas.save();
        canvas.rotate(second * 6, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 + 40, width / 2, height / 2 - 130, secondPaint);
        canvas.restore();
        //每隔1秒重绘View,重绘会调用onDraw()方法
        postInvalidateDelayed(1000);
    }
}

亿万先生官方网站,以上。


整套功效很简短,正是在显示器上显得贰个时钟,该钟表能够自行走动。

4.控件里面原来的数额被清空了,貌似从来没来过那一个环球

先来探望大家后天要兑现的2个作用图:

接下去,我们会生成二个图形对象,你能够用createElement的主意依旧用new
Image的法门,那个不纠结

3.伊始化控件

作者们在预备干活中定义了众多变量,包含钟表的水彩,指针的水彩等等许多变量,那么接下去我们须求在initView那几个措施中来起头化那些变量,以供下一步使用,OK,大家来看一看初叶化代码:

    private void initView() {
        //获取当前时间的实例
        calendar = Calendar.getInstance();
        //时钟默认宽高
        width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 256, getResources().getDisplayMetrics());
        height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 256, getResources().getDisplayMetrics());
        //初始化表针的颜色
        hourColor = Color.RED;
        minuteColor = Color.GREEN;
        secondColor = Color.BLUE;
        //初始化表针的宽度
        hourWidth = 8;
        minuteWidth = 5;
        secondWidth = 2;
        //初始化各种画笔
        circlePaint = new Paint();
        //去锯齿
        circlePaint.setAntiAlias(true);
        //设置画笔颜色
        circlePaint.setColor(Color.GREEN);
        //设置画笔style为描边
        circlePaint.setStyle(Paint.Style.STROKE);
        //设置描边的宽度
        circlePaint.setStrokeWidth(6);
        dotPaint = new Paint();
        dotPaint.setAntiAlias(true);
        dotPaint.setColor(Color.RED);
        dotPaint.setStyle(Paint.Style.FILL);
        numPaint = new Paint();
        numPaint.setColor(Color.RED);
        numPaint.setAntiAlias(true);
        //文本对齐方式
        numPaint.setTextAlign(Paint.Align.CENTER);
        hourPaint = new Paint();

        hourPaint.setColor(hourColor);
        hourPaint.setStyle(Paint.Style.FILL);
        hourPaint.setStrokeWidth(hourWidth);
        minutePaint = new Paint();
        minutePaint.setColor(minuteColor);
        minutePaint.setStyle(Paint.Style.FILL);
        minutePaint.setStrokeWidth(minuteWidth);
        secondPaint = new Paint();
        secondPaint.setColor(secondColor);
        secondPaint.setStyle(Paint.Style.FILL);
        secondPaint.setStrokeWidth(secondWidth);
    }

首先是获取2个脚下岁月的实例,因为作者要求依照手提式有线话机上的时间来呈现钟表的时刻,其次便是对表针的各个品质和画笔进行伊始化,那里的事物都很简单,我就不再一一细说,大家看代码注释,相信都能看得懂。

为了节约某个同学去翻资料,笔者表达下啥意思===>钦定了你想要在画布上制图的品种。当前唯一的法定值是
“2d”,它钦命了二维绘图,并且导致那个主意重返四个条件目的,该目的导出贰个二维绘图
API(这是网上的诠释,小编只是个搬运工)。

很多管仲觉得自定义View是权威的表示,其实不然。我们觉得自定义View难很多意况下恐怕是因为自定义View涉及到了太多的类和API,把人搞得晕头转向的,那么今天我们就从最简易的绘图API开首,带大家来一步一步深切自定义View的世界。

那显明不太融洽,于是动动脑子,你能够如此做

2.关于构造方法

世家看来,当笔者一连View之后,系统要求自小编完结它的构造方法,构造方法首要有八个,如下:

1.

public ClockView(Context context)

该构造方法是当作者在Java代码中new3个View的时候调用的。

2.

public ClockView(Context context, AttributeSet attrs)

该构造方法是当自己在布局文件中添加一个View时调用的。

3.

public ClockView(Context context, AttributeSet attrs, int defStyleAttr)

过多管仲看到第多个参数defStyleAttr之后,误以为如若我在布局文件中写了style就会调用该构造方法,其实否则,这么些构造方法系统并不会协调去调用(大家有趣味能够友善写2个style,然后在这么些艺术中打字与印刷日志,看看该格局终究会不会调用),要由我们和好显式调用(能够在其次个构造方法中调用)。那么那里的defStyleAttr毕竟是怎样意思呢?正如那几个参数的字面意思,它是咱们为自定义的View钦定的四个暗中认可样式。(后边博客大家再来详细说一下以此措施)。

除此以外,还有三个高版本采取的构造方法,我们那边暂不做牵线。

貌似情况下,我们须求在构造方法中形成都部队分开始化的操作,比如读取在XML文件中定义的习性,或然初始化画笔等等,因为大家的控件既有可能是经过Java代码实例化的,也有大概是在布局文件中通过xml添加的。如前所述,要是大家在Java代码中初阶化控件,那么将调用第一个构造方法,假设我们在xml布局文件中添加控件,那么将调用第一个构造方法。这时难点来了,那大家的早先化控件的措施应该写在万分构造方法中呢?你能够按下边那种情势来写:

    public ClockView(Context context) {
        super(context);
        initView();
    }
    public ClockView(Context context, AttributeSet attrs) {
        super(context,attrs);
        initView();
    }

在八个构造方法中分别调用初始化的主意,那种方法没不平时,可是来得你的思路没有眉目,参考Android提供的此外控件的源码,作者提出在开始化控件时服从上面那种艺术来写:

    //在代码中创建控件时调用
    public ClockView(Context context) {
        this(context, null);
    }

    //在布局文件中创建View时调用
    public ClockView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

尽管结果都平等,但是下边那种写法显得你思路很清晰。

要是你问怎么是dataurl,笔者建议您本身先去找小说看看吧,小编那有一篇不错的小说链接你能够看看:http://www.webhek.com/post/data-url.html

 具体文献链接:http://blog.csdn.net/zk437092645/article/details/8745647

 OK,到那边,你能够拿上您的接口,把那东西甩过去了。当然,并不是兼具意况都以那样子,你得和你的后端小伙伴协定好,到底要什么的数额。

——场景场景场景——–

let imgRender = new FileReader()//用来把文件读入内存,并且读取文件中的数据。FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据
imgRender.readAsDataURL(file)//将文件读取为DataURL

接下去的动作就非常粗大略了,大家看上边

if (this.$refs.imgFile.files.length !== 0) {
   this.fileImg = this.$refs.imgFile.files
} else {
   this.$refs.imgFile.files = this.fileImg
   return
 }
let picBase64 = canvas.toDataURL('image/jpeg', 1)//canvas里面是二进制二进制2222222222222
let fd = new FormData()
let blob = ImgUtil.base64ToBlob(picBase64)//不是blob,你传不了,这里不多解释这个,网上解释很多----你可以用atob()这个方法来,但是这个方法有挺大的缺陷,不过兼容性很好了,而且
你要对它进行切割切割,因为前面会有些emmit----》九九归一,来个new Blob()统统搞定
fd.append('pic', blob)

接下来大家做上边一件事

上边是vue的写法,因为近日用vue写项目,所以偷个懒。用原生的话做的法门相同

OK,那面包车型大巴手续很不难有木有。总的来说,大家依旧用canvasCtx环境指标做一些’动作’

3.我什么也不选

let canvas = document.createElement('canvas')
canvas.width = targetWidth
canvas.height = targetHeight

好了,今后你会发现,不会再有上边那种非友好的用户体验了,当然那个同等看待,有人说那是个fetch,笔者认为它很多时候是个bug…..

下一场,大家选用canvas,先安装大小,于是可以这么做

canvasCtx.fillStyle = '#fff'
canvasCtx.fillRect(0, 0, canvas.width, canvas.height)// set the default background color of png  to white
canvasCtx.drawImage(图片对象files[0], 0, 0, targetWidth, targetHeight)

2.次之次点开同样的控件,可是…..

<input
type=”file”>——在vue中大家得以给input控件几个ref属性,然后大家可以使用this.$refs.(后边这厮的属性值,其实就是一个锚点)去赢得那个控件,然后去调用那么些控件的files属性,大家就足以获得控件里面获取到的多少了。当然,他是3个对象,那几个数目也是储存在目的的三个属性个中,具体什么的温馨去打字与印刷看看。然后那个指标有个name属性,顾名思义,就是你取得的文件名,还有叁特性质是length,大家得以应用那性格格去判断控件到底里面有没有数据。假使您本人去做过,你会发觉有下边一种景况。

本人记得canvas对象暗许的大幅是300,高度是150,你本身能够打字与印刷看看

接下来我们用这几个指标的fillRect方法,能够设定那一个条件目的的横坐标、纵坐标、宽度、中度。然后是最后一步,用drawImage方法向画布上绘制图像、画布或录像。就如下边

    data () {
       return {
          fileName: null
      }
   }

相关文章