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

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

基础概念

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

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

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

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

相关推荐
天生我材必有用_吴用29 分钟前
Vue3 + VitePress 搭建组件库文档平台(结合 Element Plus 与 Arco Design Vue)—— 超详细图文教程
前端
liu****44 分钟前
基于websocket的多用户网页五子棋(八)
服务器·前端·javascript·数据库·c++·websocket·个人开发
San301 小时前
深入理解 JavaScript 函数:从基础到高阶应用
前端·javascript·node.js
ttyyttemo1 小时前
Column,rememberScrollState,记住滚动位置
前端
芒果茶叶2 小时前
并行SSR,SSR并行加载
前端·javascript·架构
vortex52 小时前
解决 Kali 中 Firefox 下载语言包和插件速度慢的问题:配置国内镜像加速
前端·firefox·腾讯云
修仙的人2 小时前
Rust + WebAssembly 实战!别再听说,学会使用!
前端·rust
maxine2 小时前
JS Entry和 HTML Entry
前端
用户63310776123662 小时前
Who is a Promise?
前端
比老马还六3 小时前
Blockly元组积木开发
前端