HarmonyOS 实现一个悬浮球

系统教程10个月前发布 [db:作者]
17 0 0

HarmonyOS 实现一个悬浮球

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

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

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

前言

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

介绍

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

效果展示

HarmonyOS 实现一个悬浮球

使用

参数名称

参数描述

参数类型

默认值

x

横坐标

Number

100

y

纵坐标

Number

100

isShow

是否显示悬浮球

Boolean

true

原理分析

1、拖拽原理

获取元素有两种方法:this.HarmonyOS 实现一个悬浮球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​​。

© 版权声明

相关文章