当前位置: 首页 > Web前端 > HTML

es6class类单例模式封装canvas圆形进度条

时间:2023-03-28 00:18:30 HTML

单例模式封装canvas圆形进度条在项目中,需要一个请求进度条效果。我尝试自己用canvas画了一个圆形的进度条。动效是直接用sleep函数加随机数来模拟的。使用了es6中的class类,以单例模式的惰性方式实例化对象。不像Java这种纯面向对象的语言,写起来还是有点别扭。从'number-precision'导入NP/***sleepfunction*@param{Number}wait*/functionsleep(wait){returnnewPromise((resolve)=>{setTimeout(resolve,wait)})}exportdefaultclassCanvasProgress{constructor({elementId,height=200,width=200}){if(elementId){this.canvas=document.getElementById(elementId)//画布节点this.canvas.height=heightthis.canvas.width=widththis.elementId=elementIdthis.height=heightthis.width=widththis.cxt=canvas.getContext('2d')//绘图上下文}//this.instance=nullthis.reset()}/***设置进度*@param{boolean}value*/setStep(value){this.step=value}/***设置是否暂停*@param{boolean}value*/setIsPause(value){this.isPause=value}/***设置是否结束*@param{boolean}value*/setIsEnd(value){this.isEnd=value}/***Reset*/reset(){this.setStep(0)this.setIsPause(false)这。setIsEnd(false)}/***获取实例,单例模式*@param{Object}config*@returns{CanvasProgress}实例对象*/staticgetInstance(config){const{elementId,height,width}=config//比较这里To使用instance实例,不能直接用thisconstins=this.instanceif(!ins||(ins&&(elementId!==ins.elementId||height!==ins.height||width!==ins.width))){this.instance=newCanvasProgress(config)}returnthis.instance}/***initialization*@param{string}e初始化类型:restart-restart*/asyncinit(e){constrestart=e==='restart'letisStarted=false//是否已经开始letisPaused=false//是否已经暂停if(!restart){isStarted=this.step>0isPaused=this.isPause||this.step===100this.reset()}this.start({isStarted,isPaused})}/***Enabled*@param{boolean}param.isStarted是否启用,如果启用,只修改step数据,继续使用启用的while循环*@param{boolean}param.isPaused是否暂停,如果暂停,则重新开始while循环*/asyncstart({isStarted,isPaused}={}){while(this.step<100){if(this.isPause)returnif(isStarted){if(isPaused)this.start()//暂停以重新开始循环return}if(this.isEnd){awaitsleep(50)this.step=parseInt(this.step)if(this.step<100){this.step++}this.draw()continue//return}//生成1-9之间的随机数constrandom=Math.round(Math.random()*8)+1constnum=NP.divide(random,Math.pow(10,random))if(this.step<80){awaitsleep(100)这.step=NP.plus(this.step,(random>5?random-5:random))}elseif(this.step>=80&&this.step<99.98){awaitsleep(10*random)this.step=NP.plus(this.step,num).toFixed(2)}else{//接口还没有返回要处理的数据,否则死循环会导致内存溢出//awaitsleep(1000)//continue//直接返回或者暂停,成功后重启this.pause()}//大于100时更正if(this.step>100)this.step=100this.draw()}}/***Pause*/pause(){this.setIsPause(true)}/***重启*/restart(){this.setIsPause(false)this.init('restart')}/***end*/end(){this.setIsEnd(true)if(this.isPause)this.restart()}/***Drawing*/draw(){this.clearRect()constx=this.width/2consty=this.height/2//灰色背景this.cxt.beginPath()this.cxt.moveTo(x,y)this.cxt.arc(x,y,x,0,Math.PI*2)this.cxt.fillStyle='#ddd'this.cxt.fill()this.cxt.closePath()//progressthis.cxt.beginPath()this.cxt.moveTo(100,100)//arc(圆心x坐标,圆心y坐标,圆半径,起始角度,结束angle[,reverse/clockwise])this.cxt.arc(x,y,x,-Math.PI*0.5,Math.PI*2*this.step/100-Math.PI*0.5,false)this.cxt.fillStyle='#57bc78'这个.cxt。fill()this.cxt.closePath()//顶层中间的白色圆圈遮挡this.cxt.beginPath()this.cxt.moveTo(x,y)this.cxt.arc(x,y,80,0,Math.PI*2)this.cxt.fillStyle="#fff"this.cxt.fill()this.cxt.closePath()//文字this.cxt.textAlign='center'this.cxt.fillStyle='#57bc78'this.cxt.textBaseline='middle'this.cxt.font='bold24pxArial'this.cxt.fillText(this.step+'%',x,y)}/***清除绘图区域*/clearRect(){this.cxt.clearRect(0,0,this.width,this.height)}/***保存图片*/saveImg(){consturl=this.canvas.toDataURL()leta=document.createElement('a')a.setAttribute('href',url)a.setAttribute('download','img.png')a.setAttribute('target','_blank')document.body.appendChild(a)a.dispatchEvent(newMouseEvent('click'))document.body.removeChild(a)}}