HarmonyOS 实现一个悬浮球

系统 OpenHarmony
很多手机都有悬浮球的功能,并且悬浮球可以有很多功能点,可以显示、隐藏与拖拽,这次我也来实现一个悬浮球的组件

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前言

很多手机都有悬浮球的功能,并且悬浮球可以有很多功能点,可以显示、隐藏与拖拽,这次我也来实现一个悬浮球的组件

介绍

这是一个悬浮球,我们可以对这个悬浮球进行拖拽,当靠近左右两边时,会自动进行隐藏

效果展示

#夏日挑战赛# HarmonyOS 实现一个悬浮球-开源基础软件社区

使用

参数名称

参数描述

参数类型

默认值

x

横坐标

Number

100

y

纵坐标

Number

100

isShow

是否显示悬浮球

Boolean

true

原理分析

1、拖拽原理

获取元素有两种方法:this.refs(“ball”),注意:获取元素不能在onInit()中获取,否则获取不到。

  • 在手指触摸事件中,将触摸时的坐标获取并存储,通过e.touches[0].localX获取。
  • 手指触摸屏幕移动的事件中,我们再获取移动后的坐标,通过移动后的坐标 - 移动前的坐标,就可以得到偏移量,最后再将当前坐标存储,依次循环。
  • 计算得到偏移量后,我们需要获取当前元素距离左边和顶部的距离,将该距离和偏移量相加,就能得到元素的最新位置。
  • 将最新的元素位置,通过动态样式赋值给元素,就能实现拖拽了。
// 手指刚触摸屏幕时触发该事件。
mousedownHandler (e) {
this.startPositionX = e.touches[0].localX;
this.startPositionY = e.touches[0].localY;
this.show()
},
// 手指触摸屏幕后移动时触发该事件
mousemoveHandler (e) {
const offsetX = e.touches[0].localX - this.startPositionX;
const offsetY = e.touches[0].localY - this.startPositionY;
const ball = this.$element("ball")
this.left = ball.getBoundingClientRect().left + offsetX
this.top = ball.getBoundingClientRect().top + offsetY
this.startPositionX = e.touches[0].localX;
this.startPositionY = e.touches[0].localY;
},

2、显示与隐藏

显示与隐藏需要配合动画效果会更好!

  • 定义显示与隐藏两个事件,当我们触发手指触摸屏幕事件时,调用显示事件;当触发手指触摸结束离开事件时,调用隐藏事件。
  • 隐藏事件的触发条件:当元素贴近左侧或者右侧时,就将元素进行隐藏,隐藏就是将元素的一半位置移除屏幕外。

通过判断条件,当元素距离左侧位置left小于0时,就将元素的一半宽度,赋值给left,注意需要设置为负值!当元素贴近右侧,此时需要获取屏幕宽度和元素宽度,因为当元素的右侧贴近屏幕右侧时,即触发隐藏事件,所以需要通过屏幕宽度-元素宽度。

  • 显示事件的触发条件:我们只需要判断元素距离左侧位置left是否小于0即可,如果小于零,就让left=0;再判断元素距离右侧是否大于屏幕宽度-元素宽度,如果是,就让元素右侧距离 = 屏幕宽度-元素宽度。
hide(){
const container = this.$element("container")
const ball = this.$element("ball")
const containerWidth = container.getBoundingClientRect().width
const ballWidth = ball.getBoundingClientRect().width
if(this.left<0){
this.left = -ballWidth/2
}else if(this.left > containerWidth-ballWidth){
this.left = containerWidth-ballWidth/2
}
},
show(){
const container = this.$element("container")
const ball = this.$element("ball")
const containerWidth = container.getBoundingClientRect().width
const ballWidth = ball.getBoundingClientRect().width
if(this.left<0){
this.left = 0
}else if(this.left > containerWidth-ballWidth){
this.left = containerWidth-ballWidth
}
}

完整代码

index.js:

// @ts-nocheck
export default {
data: {
// 标记滑块是否显示
isShow: true,
startPositionX: 0,
startPositionY: 0,
top: null,
left: null
},
onInit(){
this.top = 0;
this.left = 0;
},
// 手指刚触摸屏幕时触发该事件。
mousedownHandler (e) {
this.startPositionX = e.touches[0].localX;
this.startPositionY = e.touches[0].localY;
this.show()
},
// 手指触摸屏幕后移动时触发该事件
mousemoveHandler (e) {
const offsetX = e.touches[0].localX - this.startPositionX;
const offsetY = e.touches[0].localY - this.startPositionY;
const ball = this.$element("ball")
this.left = ball.getBoundingClientRect().left + offsetX
this.top = ball.getBoundingClientRect().top + offsetY
this.startPositionX = e.touches[0].localX;
this.startPositionY = e.touches[0].localY;
},
// 手指触摸结束离开屏幕时触发该事件。
mouseupHandler (e) {
this.hide();
},
hide(){
const container = this.$element("container")
const ball = this.$element("ball")
const containerWidth = container.getBoundingClientRect().width
const ballWidth = ball.getBoundingClientRect().width
if(this.left<0){
this.left = -ballWidth/2
}else if(this.left > containerWidth-ballWidth){
this.left = containerWidth-ballWidth/2
}
},
show(){
const container = this.$element("container")
const ball = this.$element("ball")
const containerWidth = container.getBoundingClientRect().width
const ballWidth = ball.getBoundingClientRect().width
if(this.left<0){
this.left = 0
}else if(this.left > containerWidth-ballWidth){
this.left = containerWidth-ballWidth
}
}
}

index.hml:

<div class="container" id="container">
<div
id="ball"
class="floatBall"
style="left: {{left}}px;top: {{top}}px;"
@touchstart="mousedownHandler"
@touchmove="mousemoveHandler"
@touchend="mouseupHandler">
<slot></slot>
</div>
</div>

index.css:

.container {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.floatBall {
position: absolute;
}

总结

不足点:拖拽感觉不流畅,后续还需要优化

最后,通过自定义组件,加深对HarmonyOS的开发,共建鸿蒙生态!

文章相关附件可以点击下面的原文链接前往下载:

https://ost.51cto.com/resource/2218。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-08-02 14:21:20

滑动验证码鸿蒙

2022-07-13 15:31:29

手绘板canvas鸿蒙

2022-08-01 14:07:26

canvas绘画板

2022-12-20 12:03:39

树莓派假日彩灯

2020-09-24 11:46:03

Promise

2022-01-04 11:08:02

实现Localcache存储

2017-12-12 15:24:32

Web Server单线程实现

2014-04-14 15:54:00

print()Web服务器

2023-02-26 01:37:57

goORM代码

2011-03-28 09:56:03

存储增删操作

2023-05-22 09:10:53

CSSloading 效

2023-03-01 09:39:40

调度系统

2020-08-17 08:20:16

iOSAOP框架

2022-05-13 07:42:25

JS编程题LazyMan

2022-11-29 17:34:43

虚拟形象系统

2022-06-20 15:27:00

socket对话鸿蒙

2017-01-06 13:12:11

AndroidRecyclerVie悬浮条

2016-12-20 20:16:15

科技水晶球宇宙

2021-01-04 09:12:31

集合变量

2011-07-20 10:02:01

Xcode cocoa 窗口
点赞
收藏

51CTO技术栈公众号