了解更多开源请访问:开源基础软件社区https://ost.51cto.com前言雷达扫描是很有科技感的东西。对于科幻迷来说,基本上都能在科幻电影中看到。大屏幕上,可以看到雷达扫描的绿屏效果。下面我们使用三种方法来实现这样的雷达效果。项目描述工具版本:DevEcoStudio3.0ReleaseSDK版本:3.1.1.2(APIVersion8Release)主要组件:canvas,Row,Image效果使用Image组件方式实现使用canvas组件使用Row组件的渐变属性实现实现实现过程需要注意,一个页面中只能有一个@Entry修饰符。所以在预览下面三个方法的时候,需要注意在注释中只保留一个@Entry。1、使用Image方法实现Image组件的使用是最简单的方法,直接做两张A图,一张底图,一张扫描图叠加在两张图片上,扫描图通过中心旋转圈子。下面的代码用于实现@Entry@ComponentstructRadarImg{@Stateangle:number=0;aboutToAppear(){setTimeout(()=>{this.angle=360},200)}build(){Row(){Stack(){Image($r("app.media.radar_grid"))。width(300).height(300)Image($r('app.media.radar_sector')).width(300).height(300).rotate({z:1,angle:this.angle}).animation({duration:2000,curve:Curve.Linear,iterations:-1,})}}.justifyContent(FlexAlign.Center).backgroundColor(0x111111).width('100%').height('100%')}}整体比较简单,旋转主要使用animation属性,这些可以在官网的API文档中查看。虽然Image组件的实现比较简单,但是可以实现一些复杂的雷达UI。2.使用canvas实现使用canvas需要两个组件,第一个是Canvas组件,用于绘制底图网格,第二个是Row组件,使用角度渐变属性实现扇形旋转.这里为什么不用canvas来实现呢?找了一圈,c??anvas只有线性渐变和径向渐变,没有角度渐变属性。因此,为了方便,使用row来实现。代码直接在下面。Row的渐变方法在下一个方法中讲解,最后使用动画属性animation实现扇形旋转效果@Entry@ComponentstructRadarCanvas{privatesettings:RenderingContextSettings=newRenderingContextSettings(true);privatectx:CanvasRenderingContext2D=newCanvasRenderingContext2D(this.settings)@Stateangle:number=0//绘制网格drawGrid=():void=>{letctx=this.ctx;ctx.lineWidth=1ctx.strokeStyle='green'//arr数组是需要画圆的底图letarr:Array=[150,100,50]for(leti=0;i{this.angle=360},200)}build(){行(){堆栈(){画布(this.ctx).onReady(()=>{this.drawGrid()}).width(300).height(300)Row().width(300).height(300).borderRadius(150).sweepGradient({center:[150,150],start:0,end:359,colors:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.4],['rgba(0,255,0,0.5)',1],]}).rotate({z:1,angle:this.angle}).animation({duration:2000,iterations:-1,curve:Curve.Linear})}}.justifyContent(FlexAlign.Center).backgroundColor(0x111111).width('100%').height('100%')}}3.使用Row组件实现使用Row组件的方法稍微复杂一点。这里使用了4Row组件。其实对于前端的童鞋来说,这里可能会更好一些。其实和div、css的实现类似。行组件为div,其属性为css样式。废话不多说,直接上代码(1)实现圆形,首先使用径向渐变属性(radialGradient)实现底部圆形的效果radialGradient属性有几个值需要注意。radius是渐变的半径,这里用30。渐变色colors组使用了三个数据,可以看出前两个其实是0透明度。可以理解为从第一种渐变色到第二种渐变色使用了90%。从第二个渐变色到第三个渐变色,使用10%(100%-90%)。也就是说当渐变半径为30时,90%是透明的,只有10%对绿色透明,所以得到一个圆形。然后将重复属性(重复着色)设置为true。所以在一个半径为150的圆中,可以设置150/3=5个圆。Row().width(300).height(300).borderRadius(150).radialGradient({center:[150,150],radius:30,colors:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.9],['green',1],],repeating:true,})看看效果:(2)使用两个ARow实现交叉组件,使用线性渐变属性(linearGradient)分别绘制水平和垂直效果。可以看到颜色组颜色是用5种颜色实现的,颜色1、2、4、5都是透明的。第一种颜色到第二种颜色都是透明的,渐变范围是0到49%。第二种颜色到第三种颜色的渐变范围是50%-49%=1%,即在第三种颜色到第四种颜色的50%(中间)处画一条1%的绿线。改变。第三到第五种颜色也是透明的,渐变范围也是50%。上面画好后,我们通过angle属性将线旋转90度得到一个十字。Row().width(300).height(300).borderRadius(150).linearGradient({角度:0,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.49],['绿色',0.5],['rgba(0,0,0,0)',0.5],['rgba(0,0,0,0)',1]]})Row().width(300).height(300).borderRadius(150).linearGradient({角度:90,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.49],['绿色',0.5],['rgba(0,0,0,0)',0.5],['rgba(0,0,0,0)',1]]})看看效果:(3)实现旋转的扇子扇子也是利用Row组件及其角度渐变属性(sweepGradient)实现的。Row().width(300).height(300).borderRadius(150).sweepGradient({center:[150,150],start:0,end:359,colors:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',this.flag],['rgba(0,255,0,0.5)',1],]})看看效果:最后设置Rotate旋转属性,设置旋转轴为z轴,angle角度动态更新,这样animation动画属性就会更新。最终代码:扇区代码:Row().width(300).height(300).borderRadius(150).sweepGradient({center:[150,150],start:0,end:359,colors:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',this.flag],['rgba(0,255,0,0.5)',1],]}).rotate({z:1,angle:this.angle}).animation({duration:2000,iterations:-1,curve:Curve.Linear})这里添加一个扫描周边设备的效果,动态设置一个数据源,通过ForEach动态呈现。ForEach(this.scanData,(item:any)=>{Column(){Image($r('app.media.icon')).width(28).height(28).backgroundColor('#fff').borderRadius(19)Text(item.name).fontColor('#fff').margin({top:5}).fontSize(10)}.alignItems(Horizo??ntalAlign.Center).position({x:item.x,y:item.y}).scale({x:this.w,y:this.h}).animation({duration:1000,iterations:1,curve:Curve.Friction}).opacity(this.opt)})最终代码://雷达扫描组件@Entry@ComponentstructRadar{@Stateangle:number=0;@StatescanData:any=[]@Statew:number=0;@Stateh:number=0;@Stateopt:number=1@Stateflag:number=0.4aboutToAppear(){setTimeout(()=>{this.angle=360},200)setTimeout(()=>{animateTo({duration:1000,//动画持续时间曲线:Curve.Linear,//动画曲线迭代次数:-1,//播放次数playMode:PlayMode.AlternateReverse,//动画模式onFinish:()=>{console.info('播放结束')}},()=>{this.opt=0.3})},2000)setTimeout(()=>{this.scanData=[{id:1,x:190,y:200,name:'空调'},{id:1,x:80,y:240,name:'插座'},]setTimeout(()=>{this.w=1;this.h=1;},200)},1000)}build(){Row(){Stack(){Row().width(300).height(300).borderRadius(150).radialGradient({center:[150,150],radius:30,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.9],['green',1],],重复:真,})Row().width(300).height(300).borderRadius(150).linearGradient({角度:0,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.49],['绿色',0.5],['rgba(0,0,0,0)',0.5],['rgba(0,0,0,0)',1]]})Row().width(300).height(300).borderRadius(150).linearGradient({角度:90,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',0.49],['绿色',0.5],['rgba(0,0,0,0)',0.5],['rgba(0,0,0,0)',1]]})Row().width(300).height(300).borderRadius(150).sweepGradient({center:[150,150],开始:0,结束:359,颜色:[['rgba(0,0,0,0)',0],['rgba(0,0,0,0)',this.flag],['rgba(0,255,0,0.5)',1],]}).rotate({z:1,angle:this.angle}).animation({持续时间:2000,迭代次数:-1,曲线:Curve.Linear})ForEach(this.scanData,(item:any)=>{Column(){Image($r('app.media.icon')).width(28).height(28).backgroundColor('#fff').borderRadius(19)Text(item.name).fontColor('#fff').margin({top:5}).fontSize(10)}.alignItems(Horizo??ntalAlign.Center).position({x:item.x,y:item.y}).scale({x:this.w,y:this.h}).animation({duration:1000,iterations:1,curve:Curve.Friction}).opacity(this.opt)})}.width(300).height(300)}.justifyContent(FlexAlign.Center).width('100%').height('100%').backgroundColor(0x111111)}}来看看最完整的效果:git地址https://gitee.com/yango520/yg-radar总结通过这个雷达demo,尤其是第三种方法,可以学习到颜色渐变属性中的三种渐变,线性渐变,径向渐变,角??度渐变。您还可以学习属性动画的实现。了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。