在鸿蒙中,我们想实现组件移动位置,出现在点击处,我们怎么实现呢?
基础概念
首先,我们需要知道一个基础概念
组件的位置移动本质来说是:相对于初始位置,组件在 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)
})
)
}
}
使用上面的代码,就可以实现如下图所示的功能了
"本文正在参加华为鸿蒙有奖征文征文活动"