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

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

基础概念

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

组件的位置移动本质来说是:相对于初始位置,组件在 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 分钟前
Android Debug Bridge(ADB)完全指南
android·adb
Мартин.7 分钟前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。2 小时前
案例-表白墙简单实现
前端·javascript·css
数云界2 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd2 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常2 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer2 小时前
Vite:为什么选 Vite
前端
小御姐@stella2 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing2 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd2 小时前
前端知识汇总(持续更新)
前端