当前位置: 首页 > 科技观察

HarmonyOS自定义控件JS进度条

时间:2023-03-14 20:10:26 科技观察

更多内容请访问:Harmonyos技术社区https://harmonyos.51cto.com系统提供的不能满足我们的需求。这时候我们就需要自定义一个进度条。自定义JS进度条主要涉及以下知识点:如何自定义组件以及如何引用组件定义绘制图形(draw)如何创建并执行动画(animation)如何设置自定义组件的参数(setter)如何监听自定义组件参数(getter)效果演示代码实现如何自定义组件及引用1.Js自定义组件,只需要新建一个包,直接在里面写接口、样式、逻辑代码即可。如果您需要使用该组件,只需将其完整复制到您自己的项目结构中以供参考。我们自定义一个Progress进度条控件。项目结构如下:2.使用的时候,我们需要声明自定义组件的标签,然后我们就可以使用标签了://src表示我们引用的自定义组件的文件,name表示我们为自定义组件声明一个标签名称//声明后,可以使用这个自定义标签...

如何自定义绘制图形说到自定义绘制,自然离不开canvas,首先我们添加一个标记到自定义组件并在JS文件中描述绘图:{{progressText}}在JS中定义一个draw方法,传入一个CanvasRenderingContext2D参数,我们可以理解为canvas+paint,所有的绘图我通过它调用:draw(ctx){this.display=truectx.lineWidth=this.circleWidthctx.lineCap='round'//ctx可以理解为canvas+paintctx.clearRect(0,0,this.width,this.height)//会闪烁屏幕,系统渲染问题ctx.save()//save1ctx.translate(this.width/2,this.height/2)//drawbackgroundctx.beginPath()ctx.strokeStyle=this.backgroundColorctx.arc(0,0,100,0,2*Math.PI)//r=100,参数为弧度,angle=radians/PI*180ctx.stroke()//绘图ctx.closePath()//drawprogressctx.save()ctx.rotate(-90/180*Math.PI)ctx.beginPath()ctx.strokeStyle=this.progressColorctx.arc(0,0,100,0,this.angle/180*Math.PI)//r=100,参数为弧度,角度=radian/PI*180ctx.stroke()//绘制ctx.closePath()ctx.restore()ctx.restore()//save1this.notifyChanged()}这部分逻辑不复杂,有注释,其中就是画一个圆圈背景,然后根据progress参数在圆环上画一个圆弧progress,相信做过自定义控件的同学会很熟悉如何创建和执行动画1.首先我们需要在init的时候创建一个动画对象,并设置初始动画参数:onInit(){//动画参数(具体参数类型和参数说明参考toofficialdocuments)varoptions={duration:this.animDuration,//动画持续时间direction:'normal',//播放模式easing:'linear',//Differencerfill:'forwards',//动画结束后的状态迭代:1,//执行次数begin:0,//起始值end:360.0//结束值};var_this=thisthis.animator=Animator.createAnimator(options)this.animator.onframe=function(value){//动画每一帧的回调,类似于我们熟悉的onAnimateUpdate回调_this.angle=value//刷新绘图_this.draw(_this.ctx)}...},2.然后我们需要在开始动画一个特定的时间,比如我们接收到外部传入的progress参数后,需要更新动画的起始值和结束值,开始执行e动画:onProgressChanged(oldV,newV){console.log("onProgressChangedfrom:"+oldV+"to:"+newV)this.initWidget()//进度值范围限制为[0,1]if(oldV>=1){oldV=1}if(newV>=1){newV=1}//更新动画起止参数varoptions={duration:this.animDuration,direction:'alternate-reverse',easing:'linear',fill:'forwards',iterations:1,begin:oldV*360,end:newV*360};??this.animator.update(options)//开始执行动画this.animator.play()},如何设置自定义组件的参数1.我们的自定义组件不能像以前那么简单,暴露一个男的外部调用的open方法由于其数据驱动的设计,我们可以定义一些自定义属性参数,当外部修改参数时,我们可以接收信息并采取主动行动(setters):props:['progress',//progress'backgroundColor',//圆形背景色'progressColor'//progress前景色],...2.监听这些对外暴露的属性值变化(监听器):onInit(){...//监听自定义属性值的变化this.$watch('progress','onProgressChanged')this.$watch('backgroundColor','onBackgroundChanged')this.$watch('progressColor','onForegroundChanged')...},//backgroundColor变化时触发回调onBackgroundChanged(oldV,newV){this.backgroundColor=newV},//progressColor变化时触发回调onForegroundChanged(oldV,newV){this.progressColor=newV},//进度变化onProgressChanged(oldV,newV){console.log("onProgressChangedfrom:"+oldV+"to:"+n时会触发回调ewV)this.initWidget()if(oldV>=1){oldV=1}if(newV>=1){newV=1}varoptions={duration:this.animDuration,direction:'alternate-reverse',缓动:'linear',fill:'forwards',iterations:1,begin:oldV*360,end:newV*360};??this.animator.update(options)this.animator.play()},3..外部设置参数,当外部改变这些参数时,会触发我们自定义组件内部的回调方法,并进行刷新逻辑:...
如何监控自定义组件的参数上面我们讲了如何改变组件的内部参数自定义组件属性,本质上是典型的观察者模式同理,外部调用者需要监听我们自定义组件的参数变化,也是这样:1.首先,我们需要在自定义组件中定义一个被观察的对象(key),当该对象的值发生变化时向外部发送消息:notifyChanged(){//currentAngle,currentProgress是被观察的对象,key-value结构,value是我们向外界发送的值//注意:驼峰式命名this。$emit("currentAngle",this.angle)this.$emit("currentProgress",Math.ceil(this.angle/3.6)/100)this.progressText=Math.ceil(this.angle/3.6)+"%"},2.外部使用观察者需要注册监听回调方法来监听被观察对象(key)://通过@current-angle和@current-progress监控这个参数。注意参数前加“@”,参数按驼峰命名方式拆分成词,每个词用“-”隔开...
//当自定义组件内的currentAngle和currentProgres当s发生变化时,会触发下面的回调方法通知外部用户.detail)}其他重点1.标签的绘制内容默认不显示。我们可以在初始化时监听首帧回调,主动刷新一次:onInit(){...//监听首帧,触发第一次绘制,类似attachToWindow的触发时机){_this.initWidget()_this.draw(_this.ctx)})},2.如何获取自定义组件的宽高信息,在API6+系统中已经提供了相关获取方法,类似于读取宽高信息在onSizeChanged:initWidget(){console.log("initwidget")if(this.ctx===null){//获取标签元素letwidget=this.$element('progress-bar');this.ctx=widget.getContext('2d',{antialias:true})//获取宽高,并计算绘制环的宽高、中心点、半径信息this.width=widget.getBoundingClientRect(.widththis.height=widget.getBoundingClientRect().heightthis.centerX=widget.getBoundingClientRect().left+this.width/2this.centerY=widget.getBoundingClientRect().top+this.height/2console.log("canvassize="+this.width+","+this.height)console.log("canvascenter="+this.centerX+","+this.centerY)}},3.canvas画布和我们平时理解的不一样。它有一个绘图缓存,所以当每一帧刷新时,我们需要在绘制之前清除之前绘制的内容。目前鸿蒙清除画布时,可能存在闪烁问题。以上就是实现自定义JS进度条的核心代码。源码:JsProgress更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com