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

【甜甜酱OH实践】OpenHarmonyArkUI实现WebAPI拖拽效果

时间:2023-03-11 23:35:12 科技观察

更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com大家经常浏览网页,有没有发现按住鼠标拖动图片后,可以拖出一个幻影。对于WEB前端,WebAPI提供了拖拽接口,可以轻松实现这样的效果。对于OpenHarmony应用开发的朋友,我们也可以使用onTouch来实现这样的效果。拖拽效果展示完整代码查看:https://gitee.com/hytyj_hamstermie/tian-open-document.gitArkUI实现WebAPI拖拽拖拽效果/demo/page.ets实现思路实现思路很简单。我们设置了一个模拟块,它总是堆叠在最上面。模拟块最初是隐藏的。当用户触摸一个绑定了触摸事件的固定块时,模拟块会复制固定块的所有样式和内容,并获取固定块的位置。显示模拟块,覆盖在固定块上。在触摸事件持续期间,模拟块会根据手指的触摸坐标更新自己的位移。触摸事件结束后,模拟块消失。开发环境IDE:DevEcoStudio3.0beta2BuildVersion3.0.0.800SDKVersion:8supportSystem"standard"系统版本:OpenHarmony3.1beta实际效果如图:定义块样式首先,我们定义固定块的样式。使用@Extend装饰器,我们可以更快地复制块样式。在IDE中使用@Extend装饰器会报错Duplicatefunctionimplementation。但是OpenHarmony支持@Extend装饰器。推测可能是IDE的问题,建议使用typescript忽略。//单行忽略//@ts-ignore//忽略全文//@ts-nocheck//取消忽略全文//@ts-check请谨慎使用@ts-nocheck,因为方便,我用了ignore之前直接全文,导致调试的时候,很多语法问题没有修复回来。undefined//定义块组数据@StateblockInfos:any[]=[{text:"A",textsize:30,color:"#ffffff",bgcolor:"#336699",opacity:1},{text:"B",文本大小:30,颜色:"#ffffff",bgcolor:"#339961",不透明度:1},{文本:"C",文本大小:30,颜色:"#ffffff",bgcolor:"#929933",opacity:1},{text:"D",textsize:30,color:"#ffffff",bgcolor:"#995033",opacity:1}]简单块样式相关数据:文本内容文本大小文本颜色背景颜色透明度定义渲染固定块方法@Builder装饰器必须使用struct中的@Builder装饰方法定义默认参数,主要传入参数放在最上面:文本内容背景颜色透明度触摸事件方法//可以设置默认参数@BuilderItemBlock(text:string,bgcolor:Color,opacity:number,touchevent:any,textcolor:Color=Color.White,textsize:number=30,width:number=90,height:number=90,){Flex({alignItems:项目对齐。Center,justifyContent:FlexAlign.Center}){Text(text).blockTextStyle(textcolor,textsize)}.blockStyle(opacity,bgcolor,width,height).onTouch(touchevent)}定义渲染模拟块方法,定义相关状态模拟块数据//位移坐标x@Statex:number=0//位移坐标y@Statey:number=0//是否显示@StateflayerShow:boolean=false//模拟块宽度@StateflayerWidth:number=0//模拟方块高度@StateflayerHeight:number=0//模拟方块文字内容@StateflayerText:string=""//模拟方块文字大小@StateflayerTextSize:number=30//模拟方块文字颜色@StateflayerTextColor:颜色=颜色。White//模拟方块背景色@StateflayerBgColor:Color=Color.Blackimplements@BuilderDragBlock(text:string=this.flayerText,bgcolor:Color=this.flayerBgColor,textcolor:Color=this.flayerTextColor,textsize:number=this.flayerTextSize,width:number=this.flayerWidth,height:number=this.flayerHeight,opacity:number=1){Flex({alignItems:ItemAlign.Center,justifyContent:FlexAlign.Center}){Text(this.flayerText).blockTextStyle(textcolor,textsize)}.blockStyle(opacity,bgcolor,width,height).position({x:this.x,y:this.y})}Layout//堆栈容器Stack(){//FixedblockFlex({direction:FlexDirection.Column,alignItems:ItemAlign.Center,justifyContent:FlexAlign.Center}){Grid(){//OpenHarmony3.1beta已修复ForEach返回索引失败问题ForEach(this.blockInfos,(info,index)=>{GridItem(){Flex({direction:FlexDirection.Column,alignItems:ItemAlign.Center,justifyContent:FlexAlign.SpaceAround}){this.ItemBlock(info.text,info.bgcolor,info.opacity,(e:TouchEvent)=>{//这里注意,是拖放的重点})}}})}.columnsTemplate('1fr1fr1fr').rowsTemplate('1fr1fr').backgroundColor("#dddddd").margin(20).height(300)}.backgroundColor("#f8f8f8").width("100%").height("100%")//模拟块,堆叠在顶层,通过flayerShow控制其显示if(this.flayerShow){this.DragBlock()}}.width('100%').height('100%')理解onTouch是指HarmonyOS的触摸事件:https://developer.harmonyos.com/cn/docs/documentation/doc-references/ts-universal-events-touch-0000001158261221OpenHarmonyOpenHarmony与HarmonyOSAPI文档的区别,多了一个返回在TouchEvent中,target对象target携带了当前绑定的触摸组件的基本信息,方便我们实现一些能力。TouchEvent信息示例:{"timestamp":345459939477,"target":{"area":{"pos":{"x":0,"y":30},"globalPos":{"x":88.33333333333333,"y":520},"width":90,"height":90}},"touches":[{"type":0,"id":1,"screenX":126,"screenY":571.5,“x”:37.66666793823242,“y”:51.5}],“type”:0,“changedTouches”:[{“type”:0,“id”:1,“screenX”:126,“screenY”:571.5,"x":37.66666793823242,"y":51.5}]}Touch事件TouchEvent对象描述属性TouchObject对象描述TouchType枚举描述TargetObject对象描述AreaObject对象描述onTouch方法的实现现在让我们实现最重要的onTouch方法之一拖放的实现会有三个阶段:手指按下,对应TouchType.Down手指拖动,对应TouchType.Move手指松开,对应TouchType.Upif(e.type===TouchType.Down){//手指按下}elseif(e.type===TouchType.Move){//手指拖动}elseif(e.type===TouchType.Up){//手指松开}在IDE中按下手指,得到组件的坐标,组件的高宽,返回的数据类型不是API文档中写的数字,而是一个Length类型。Length是长度类型。由于我们之前定义的数据类型是number,这里我们可以使用as类型断言来断言当前数据类型为number。if(e.type===TouchType.Down){//复制块样式letareainfo=e.target.area//断言数据类型this.flayerWidth=areainfo.widthasnumberthis.flayerHeight=areainfo.heightasnumberthis.flayerText=info.textthis.flayerTextSize=info.textsizethis.flayerTextColor=info.colorthis.flayerBgColor=info.bgcolor//获取初始坐标//Assertdatatypethis.x=areainfo.globalPos.xasnumberthis.y=areainfo.globalPos.yasnumber//完成复制,显示模拟方块this.flayerShow=true//设置相应方块中的透明度数据为0.2this.blockInfos[index].opacity=0.2}手指拖动到模拟块的坐标不断更新为手指的触摸坐标。我们要拖动块的中心点,所以坐标必须偏移。偏移量为:块宽/2,块高/2。elseif(e.type===TouchType.Move){this.x=e.touches[0].screenX-this.flayerWidth/2this.y=e.touches[0].screenY-this.flayerHeight/2}手指释放手指释放后,拖动操作也终止,所以模拟块应该消失。elseif(e.type===TouchType.Up){this.flayerShow=falsethis.blockInfos[index].opacity=1}这样简单的拖拽就完成了,打开Previewer看看效果。问题是虽然在模拟器上运行良好,但是在开发板上却出现了问题:应用程序在开发板上运行时,TouchEvent中的所有值都比预期值小1倍。拖动的时候,会发现位置偏移很大。这个问题已经作为issue提交了,希望OpenHarmony能够解决。issue:https://gitee.com/openharmony/docs/issues/I4TF75另外由于没有GPU支持,在开发板上会很卡。在开发板上查看要查看的开发板(3516/rk3568)好友。你可以把touchEvent返回一个*2的值看看正常效果。if(e.type===TouchType.Down){letareainfo=e.target.area//返回的高宽信息*2this.flayerWidth=areainfo.widthasnumber*2this.flayerHeight=areainfo.heightasnumber*2this.flayerText=info.textthis.flayerTextSize=info.textsizethis.flayerTextColor=info.colorthis.flayerBgColor=info.bgcolorthis.flayerShow=true//返回坐标*2this.x=areainfo.globalPos.x作为数字*2this.y=areainfo.globalPos.y作为数字*2this.blockInfos[index].opacity=0.2}elseif(e.type===TouchType.Move){this.x=e.touches[0].screenX*2-this.flayerWidth/2this.y=e.touches[0].screenY*2-this.flayerHeight/2}更多内容请访问:鸿蒙科技华为共建社区官方https://harmonyos.51cto.com