鸿蒙怎么实现组件移到点击处,看这一篇就够了

在鸿蒙中,我们想实现组件移动位置,出现在点击处,我们怎么实现呢?

基础概念

首先,我们需要知道一个基础概念

组件的位置移动本质来说是:相对于初始位置,组件在 x、y 轴上移动一定距离

如下图所示:以组件的左上角为标准,可以看到组件的移动距离

而鸿蒙为我们提供了一个方法 translate,可以让组件在 x、y 轴上进行移动

kotlin 复制代码
Text("111")
  .width(30)
  .height(30)
  .translate({ 
    x: this.positionX, 
    y: this.positionY, 
    })

怎么计算移动位置

我们现在知道了,可以 translate 来让组件进行移动,那么现在只需要解决一个问题就行了:让组件在 x、y 轴上移动的后位置和手指点击的位置一样

而这一点就是最难的一点,下面我们就来一点点分析

在进行计算距离时,有以下注意点:

  • 鸿蒙的点击事件是相对于整个屏幕的
  • 组件初始位置在父容器中,而父容器不一定完全和屏幕相等,这时需要减去父容器相对于屏幕位置
  • 组件初始位置不一定父容器左上角,这时需要减去组件相对于父容器位置

所以可以得到下面的公式:

组件移动位置 = 点击位置 - 父容器相对于屏幕位置- 组件相对于父容器位置 - 组件半径(居中显示)

如果组件原始的位置在父组件的左上角,那么公式就可以进行简化:

组件移动位置 = 点击位置 - 父容器相对于屏幕位置 - 组件半径

代码

typescript 复制代码
import { LIKE_ICON_SIZE, TAP_GESTURE_COUNT } from './Constant'

@Component
export default struct LikeComponent {
  @State positionX: number = 0
  @State positionY: number = 0
  ICON_SIZE = 50

  onClick(event: GestureEvent) {
    if (event && event.fingerList && event.fingerList.length > 0) {

      // 因为父组件不是铺满整个屏幕的,而点击事件的的位置是全局的,所以需要减去容器左上角的位置
      const position = event.target.area.globalPosition
      const areaX: number = position.x as number ? position.x as number : 0
      const areaY: number = position.y as number ? position.y as number : 0

      // 因为图片是左上角对齐的,要让图片显示在手指位置,需要减去图片的半径
      const ImageRadius = this.ICON_SIZE / 2

      // 手指位置 - 容器左上角位置 - 图片半径
      // 注意:因为这里图片的初始位置是左上角,如果放在中间,还需要减去图片相对于容器的位置
      this.positionX = event.fingerList[0].globalX - areaX - ImageRadius
      this.positionY = event.fingerList[0].globalY - areaY - ImageRadius
    }
  }

  build() {
    // 初始位置在左上角
    Stack({ alignContent: Alignment.TopStart }) {
      Text("111")
        .width(this.ICON_SIZE)
        .height(this.ICON_SIZE)
        // 数据改变时,改变组件位置
        .translate({ x: this.positionX, y: this.positionY, z: 0 })
    }
    .height('80%')
    .width('100%')
    .parallelGesture(
      TapGesture({ count: 1 })
        .onAction((event) => {
          this.onClick(event)
        })
    )
  }
}

使用上面的代码,就可以实现如下图所示的功能了

"本文正在参加华为鸿蒙有奖征文征文活动"

相关推荐
程序猿阿伟4 分钟前
《探秘鸿蒙Next:非结构化数据处理与模型轻量化的完美适配》
华为·harmonyos
九月十九17 分钟前
AviatorScript用法
java·服务器·前端
编程、小哥哥28 分钟前
python操作mysql
android·python
Couvrir洪荒猛兽1 小时前
Android实训十 数据存储和访问
android
_.Switch1 小时前
Python Web开发:使用FastAPI构建视频流媒体平台
开发语言·前端·python·微服务·架构·fastapi·媒体
菜鸟阿康学习编程2 小时前
JavaWeb 学习笔记 XML 和 Json 篇 | 020
xml·java·前端
索然无味io2 小时前
XML外部实体注入--漏洞利用
xml·前端·笔记·学习·web安全·网络安全·php
HarmonyOS_SDK2 小时前
巧用多目标识别能力,帮助应用实现智能化图片解析
harmonyos
ThomasChan1233 小时前
Typescript 多个泛型参数详细解读
前端·javascript·vue.js·typescript·vue·reactjs·js
爱学习的狮王3 小时前
ubuntu18.04安装nvm管理本机node和npm
前端·npm·node.js·nvm