canvas 简易的加载进度条-阿里云开发者社区

开发者社区> 淡色的云> 正文

canvas 简易的加载进度条

简介: 做一个web app,想在第一次或者更新的时候,有一个更新进度条,我个人比较喜欢圆的那种。  canvas + svg高低配,应该还不错的。顺便一提,canvas用来压缩图片也是么么哒的。  先看下效果图,我咋觉得边有点虚。
+关注继续查看

做一个web app,想在第一次或者更新的时候,有一个更新进度条,我个人比较喜欢圆的那种。 

canvas + svg高低配,应该还不错的。顺便一提,canvas用来压缩图片也是么么哒的。

 先看下效果图,我咋觉得边有点虚。基本的样子有了,但是美观,美观,我要美观,下次再来。

 

进度条

 

原理就是绘制圆和文本绘制。

特别说明:

1. 会自动计算canvas的宽高,取最大值,并重设宽高为最大值

2. 有简单的计算逻辑,让 百分比的文本居中

3. 超大的边宽会被限制

上代码。


class CanvasProgress {
    constructor(cv, options = {
        bgColor: '#123456',
        cBgColor: 'green',
        edgeWidth: 20
    }) {

        if (!cv || !cv.getContext) {
            throw new Error('参数cv为空或者getContext方法未定义')
        }

        this._ctx = cv.getContext('2d')
        this._diameter = this._getDiameter(cv)  //直径
        this._radius = Math.ceil(this._diameter / 2) //半径
        this._options = Object.assign({
            bgColor: '#123456', //未加载的背景色
            cBgColor: 'green', //已加载的背景色
            edgeWidth: 20,     //边款
            textMaxWidth: this._radius  //进度文本最大长度
        }, options)
        this._options.edgeWidth = Math.min(this._radius * 0.28, this._options.edgeWidth) //重新计算
        this._circleParams = {
            x: this._radius,//圆心的x轴坐标值
            y: this._radius,//圆心的y轴坐标值
            r: Math.floor(this._radius - this._options.edgeWidth / 2 - 1) //圆的半径
        }

        this._resizeCanvas(cv)  //调整canvas宽高一致
        this._initialize() //绘制背景圆
    }


    /**
     * 通过canvas获得直径
     * @param {*canvas对象} cv 
     */
    _getDiameter(cv) {
        return Math.max(cv.height || 0, cv.width || 0) || 200
    }

    /**
     * 进度转换角度
     * @param {*进度} progress 
     */
    _getAngle(progress) {
        return (progress / 100) * Math.PI * 2
    }

    _resizeCanvas(cvProgress) {
        cvProgress.width = cvProgress.height = this._diameter
    }

    /**
     * 调整canvas宽高一致
     */
    _initialize() {
        let ctx = this._ctx
        // 开始一个新的绘制路径
        ctx.beginPath()
        //设置弧线的颜色为蓝色
        ctx.strokeStyle = this._options.bgColor
        ctx.lineWidth = this._options.edgeWidth
        //以canvas中的坐标点(100,100)为圆心,绘制一个半径为50px的圆形
        ctx.arc(this._circleParams.x, this._circleParams.y, this._circleParams.r, 0, Math.PI * 2, false)
        //按照指定的路径绘制弧线
        ctx.stroke()
    }

    /**
     * 更近进度
     * @param {*进度 0-100} progressValue 
     * @param {*绘制圆的设置} circleSettings 
     * @param {*绘制文本的设置} progressTextSettings 
     */
    updateProgress(progressValue, circleSettings, progressTextSettings) {
        if (progressValue <= 0) {
            return
        }
        this._updateCircle(progressValue, circleSettings)
        this._updateProgressText(progressValue, progressTextSettings)
    }

    /**
     * 绘制圆
     * @param {*进度} progressValue 
     * @param {*设置} settings 
     */
    _updateCircle(progressValue, settings) {
        let ctx = this._ctx
        ctx.beginPath()
        let angle = this._getAngle(progressValue)

        ctx.strokeStyle = this._options.cBgColor
        ctx.lineWidth = this._options.edgeWidth

        if (settings) {
            Object.keys(settings).forEach(k => {
                ctx[k] = settings[k]
            })
        }

        ctx.arc(this._circleParams.x, this._circleParams.y, this._circleParams.r, 0 + Math.PI * 1.5, angle + Math.PI * 1.5, false)
        ctx.stroke()
    }

    /**
     * 绘制进度文本
     * @param {*进度} progressValue 
     * @param {*设置} settings 
     */
    _updateProgressText(progressValue, settings) {

        if (progressValue < 0 || progressValue > 100) {
            return
        }

        let ctx = this._ctx,
            r = this._radius,
            fontSize = this._getFontSize(settings)
        ctx.clearRect(r * 0.5, r * 0.5, r, r)
        ctx.font = `${fontSize}px sans-serif`
        ctx.fillStyle = this._getTextGradient()
        if (settings) {
            Object.keys(settings).forEach(k => {
                ctx[k] = settings[k]
            })
        }

        ctx.fillText(progressValue + '%', this._circleParams.x - this._options.textMaxWidth / 2, this._circleParams.y + fontSize / 2, this._options.textMaxWidth)
    }

    /**
     * 渐变设置
     */
    _getTextGradient() {
        var gradient = this._ctx.createLinearGradient(0, 0, 100, 0);
        gradient.addColorStop("0", "red");
        gradient.addColorStop("0.5", "blue");
        gradient.addColorStop("1.0", "green");
        return gradient
    }

    /**
     * 获得当前文字大小
     * @param {*设置} settings 
     */
    _getFontSize(settings) {
        if (settings && settings.font) {
            let matchItem = settings.font.match(/\d{1,2}/)
            if (matchItem) {
                return Number.parseInt(matchItem[0])
            }
        }
        return this._radius * 0.6
    }

}

  

 

调用代码:

<!DOCTYPE>
<html>

<head>
    <title> canvas 原型进度条</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
</head>

<body style="margin:5% 10% 0 10%">
    <div>
        <canvas id="cvProgress" height="250" width="15">
    </div>
    <script src="CanvasProgress.js"></script>
</body>
<script>
    let ps = new CanvasProgress(cvProgress, {
        edgeWidth: 50       
    }), progress = 0
    let tickets = setInterval(function () {
        progress += 5
        ps.updateProgress(progress,null,{               
        })
        if (progress > 100) {
            clearInterval(tickets)
        }
    }, 100)

</script>

</html>

 

源码地址:https://github.com/xiangwenhu/BlogCodes/tree/master/client/canvas

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9719 0
Java Class类的使用 和 动态加载类
Class类 1)在面向对象的世界里,万事万物皆对象。 类是对象,类是java.lang.Class类的实例对象。 There is a class named Class 2)Foo的实例对象如何表示 Foo foo1=new Foo();//foo1就表示出来了 ...
635 0
Glide 加载图片背景变绿
解决方案:   Glide.with(mContext).load(url).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(imageView);
662 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13441 0
Lua模块的加载与内存释放
今天早上听说一件事情让我觉得很诡异的事情:公司线上的一款游戏,加载一份配置资源后,内存涨了几十M,然后内存再也下不来了。因为好奇,所以要来了最大的一个配置文件(4.5M,去除空格与换行后的大小),进行测试。
1539 0
Glide 资源加载流程分析
转载请标明地址 QuincySx: http://www.jianshu.com/p/eed7054e3722 这是 Glide 的第二篇,在上一篇中讲的都是大概流程,直接阅读起来可能比较困难,推荐结合源码浏览,在这一篇中就讲资源加载,所以贴上来的源码就会多一些。
837 0
+关注
淡色的云
不争不弃,喜欢淡色的云。
55
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载