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

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

基础概念

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

组件的位置移动本质来说是:相对于初始位置,组件在 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)
        })
    )
  }
}

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

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

相关推荐
啟明起鸣2 分钟前
【Nginx 网关开发】上手 Nginx,简简单单启动一个静态 html 页面
运维·c语言·前端·nginx·html
vortex55 分钟前
深度字典攻击(实操笔记·红笔思考)
前端·chrome·笔记
我是伪码农7 分钟前
Vue 1.30
前端·javascript·vue.js
利刃大大15 分钟前
【Vue】默认插槽 && 具名插槽 && 作用域插槽
前端·javascript·vue.js
前端不太难17 分钟前
HarmonyOS 项目中如何拆分共用层与形态模型
华为·状态模式·harmonyos
艳阳天_.19 分钟前
web 分录科目实现辅助账
开发语言·前端·javascript
Facechat22 分钟前
鸿蒙开发入坑篇(九):本地数据库 (RDB) 深度解析
数据库·华为·harmonyos
2501_9219308325 分钟前
React Native 鸿蒙跨平台开发:LinearGradient 径向渐变
react native·react.js·harmonyos
2601_9495936525 分钟前
React Native 鸿蒙跨平台开发:LinearGradient 实战案例集
react native·react.js·harmonyos
小白640236 分钟前
2025年终总结-迷途漫漫,终有一归
前端·程序人生