当前位置: 首页 > news >正文

通过获取异步加载JS文件进度实现一个canvas环形loading图

1.整理下思路,要获取异步加载JS文件的进度要怎么做?

答:将需要异步载入的文件放进一个数组中。如下。

const scriptArr = ['./test_1.js', './test_3.js', './test_4.js', './test_5.js'];

然后动态创建script标签插入到body标签中。通过script.onload获取JS是否加载完毕

2.怎么绘制一个动态的canvas环形loading加载图?

答:需要用到的canvas 核心Api有:ctx.arc()。这是绘制园环的必须api.

3.既然能获取到加载完毕的回调函数,也能够创建一个canvas loading实例,如何把它们关联到一起整合到一块?

  1. 编写一个circleProgress类,用来创建环形loading实例

        class CircleProgress {
            constructor(ctxs, width, height, arc) {
                this.ctx = ctxs
                this.width = width
                this.height = height
                this.arc = arc
    
                this.setArea(width, height)
            }
            //设置canvas的宽高
            setArea(width, height) {
                this.ctx.canvas.width = width
                this.ctx.canvas.height = height
            }
            //清除画布
            clearFill() {
                this.ctx.clearRect(0, 0, this.width, this.width);
            }
             //绘制环形进度图的背景 颜色是可配置的 
            fillBg() {
                this.ctx.beginPath();
                this.ctx.lineWidth = this.arc;
                this.ctx.strokeStyle = '#ccc';
                this.ctx.arc(this.width / 2, this.width / 2, 45, 0, 2 * Math.PI);
                this.ctx.stroke();
            }
            //绘制进度条
            fillArc(x) {
                this.ctx.beginPath();
                this.ctx.lineWidth = this.arc;
                this.ctx.strokeStyle = 'yellow';
                this.ctx.arc(this.width / 2, this.width / 2, 45, -90 * Math.PI / 180, (x * 3.6 - 90) * Math.PI / 180);
                this.ctx.stroke();
            }
            //绘制中心数字展示
            fillText(x) {
                this.ctx.font = '14px' + ' Arial';
                this.ctx.fillStyle = 'red';
                this.ctx.textBaseline = "middle";
                this.ctx.textAlign = 'center';
                this.ctx.fillText(x.toFixed(1) + '%', this.width / 2, this.width / 2);
            }
            //总绘制方法
            fill(x) {
                this.fillBg();
                this.fillArc(x);
                this.fillText(x);
            }
    
        }

    大概就是这个样子
    clipboard.png

  2. 获取当前JS,加载进度
    function jsProgress(circle, eachs, max, scriptArr) {
        let currentIndex = 0;
        //遍历所有文件名
        for (let i = 0; i < scriptArr.length; i++) {
            let scriptNode = document.createElement('script');
            scriptNode.src = scriptArr[i];
            
            //插入创建好的script引用节点
            document.getElementById('bodys').appendChild(scriptNode);
            
            //创建分布值 每个文件占据的进度值 比如4个文件 每个文件占据100/4=25
            let steps = 0;
            
            //插入的文件加载完毕后的回调
            scriptNode.onload = function() {
                //按照每20毫秒一帧渲染canvas画布 以展示出动态的加载效果
                let ani = setInterval(function() {

                    //此处可以优化,有好的建议可以告诉我
                    if (steps <= max || steps == 100) {
                        circle.clearFill();
                        if (steps > 100) {
                            steps = 100
                        }

                        circle.fill(steps)
                        steps++
                    } else {
                        clearInterval(ani)
                        if (max <= 100) {
                            max = max + eachs
                            currentIndex++;
                        }
                        if (currentIndex == scriptArr.length) {
                            console.log(`全部JS加载完成`)
                        }
                        console.log(`sciprtNode${i}已加载完成`)
                    }
                }, 20)

                
                
            }
        }
    }

最终效果

clipboard.png

附录:全部代码

        <script>
        class CircleProgress {
            constructor(ctxs, width, height, arc) {
                this.ctx = ctxs
                this.width = width
                this.height = height
                this.arc = arc

                this.setArea(width, height)
            }

            setArea(width, height) {
                this.ctx.canvas.width = width
                this.ctx.canvas.height = height
            }

            clearFill() {
                this.ctx.clearRect(0, 0, this.width, this.width);
            }

            fillBg() {
                this.ctx.beginPath();
                this.ctx.lineWidth = this.arc;
                this.ctx.strokeStyle = '#ccc';
                this.ctx.arc(this.width / 2, this.width / 2, 45, 0, 2 * Math.PI);
                this.ctx.stroke();
            }

            fillArc(x) {
                this.ctx.beginPath();
                this.ctx.lineWidth = this.arc;
                this.ctx.strokeStyle = 'yellow';
                this.ctx.arc(this.width / 2, this.width / 2, 45, -90 * Math.PI / 180, (x * 3.6 - 90) * Math.PI / 180);
                this.ctx.stroke();
            }

            fillText(x) {
                this.ctx.font = '14px' + ' Arial';
                this.ctx.fillStyle = 'red';
                this.ctx.textBaseline = "middle";
                this.ctx.textAlign = 'center';
                this.ctx.fillText(x.toFixed(1) + '%', this.width / 2, this.width / 2);
            }

            fill(x) {
                this.fillBg();
                this.fillArc(x);
                this.fillText(x);
            }

            testFn() {
                ctxs.beginPath();
                ctxs.lineWidth = 10;
                ctxs.strokeStyle = '#ccc';
                ctxs.arc(50, 50, 45, 0, 2 * Math.PI);
                ctxs.stroke();
            }

        }

        function jsProgress(circle, eachs, max, scriptArr) {
            let currentIndex = 0;

            for (let i = 0; i < scriptArr.length; i++) {
                let scriptNode = document.createElement('script');
                scriptNode.src = scriptArr[i];

                document.getElementById('bodys').appendChild(scriptNode);

                let steps = 0;

                scriptNode.onload = function() {
                    let ani = setInterval(function() {


                        if (steps <= max || steps == 100) {
                            circle.clearFill();
                            if (steps > 100) {
                                steps = 100
                            }

                            circle.fill(steps)
                            steps++
                        } else {
                            clearInterval(ani)
                            if (max <= 100) {
                                max = max + eachs
                                currentIndex++;
                            }
                            console.log(`sciprtNode${i}已加载完成`)
                  
                            if (currentIndex == scriptArr.length) {
                                console.log(`全部JS加载完成`)
                            }
                        }
                    }, 20)

                }
            }
        }

        const scriptArr = ['./test_1.js', './test_3.js', './test_4.js', './test_5.js'];

        let canvasNode = document.getElementById('canvas'),
            ctxs = canvasNode.getContext("2d");

        let circle = new CircleProgress(ctxs, 100, 100, 10),
            eachs = parseInt(100 / scriptArr.length),
            max = eachs


        jsProgress(circle, eachs, max, scriptArr);

        // circle.testFn()
    </script>

相关文章:

  • PyTorch快速入门教程五(rnn)
  • 故障排查
  • 腾讯云服务器 安装监控组件
  • CRM系统客户形成需求和认知的五大因素
  • 【leetcode】55. Jump Game
  • node.js 学习(二)
  • 内华达州PUC特准3.2万光伏用户优惠太阳能补贴费率
  • 文件读,写,拷贝,删除
  • 神州数码网真解决方案助山西电力信息高速化
  • 大数据正在改变企业决策方式
  • Centos 7 配置tomcat服务器
  • 常用软件测试工具的分析
  • 让git更高效--文末有福利
  • 力争大数据及关联产业规模2020年达300亿元
  • python 操作asdl
  • ----------
  • bearychat的java client
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Facebook AccountKit 接入的坑点
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • JavaScript实现分页效果
  • 第2章 网络文档
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 前端性能优化--懒加载和预加载
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 使用权重正则化较少模型过拟合
  • 我的业余项目总结
  • 与 ConTeXt MkIV 官方文档的接驳
  • linux 淘宝开源监控工具tsar
  • # Maven错误Error executing Maven
  • #HarmonyOS:Web组件的使用
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (理论篇)httpmoudle和httphandler一览
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • ../depcomp: line 571: exec: g++: not found
  • .htaccess 强制https 单独排除某个目录
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Core中的去虚
  • .net wcf memory gates checking failed
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • .net连接oracle数据库
  • .so文件(linux系统)
  • @Autowired多个相同类型bean装配问题
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [ 环境搭建篇 ] 安装 java 环境并配置环境变量(附 JDK1.8 安装包)
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [1204 寻找子串位置] 解题报告
  • [2544]最短路 (两种算法)(HDU)
  • [AutoSar]BSW_Com02 PDU详解
  • [ccc3.0][数字钥匙] UWB配置和使用(二)
  • [HTML]Web前端开发技术7(HTML5、CSS3、JavaScript )CSS的定位机制——喵喵画网页
  • [JavaWeb学习] idea新建web项目
  • [java基础揉碎]关系运算符(比较运算符)逻辑运算符赋值运算符三元运算符运算符的优先级
  • [Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解