
回复
这篇文章介绍一下旋转手势(RotationGesture)的触发条件和回调信息。还有控制组件旋转的rotate介绍。
旋转手势处理器配置参数:RotationGestureHandlerOptions
名称 | 说明 |
---|---|
fingers | 触发捏合的最少手指数[2, 5] |
angle | 触发旋转手势的最小改变度数 |
isFingerCountLimited | 是否检查触摸屏幕的手指数量 |
GestureEvent对象在RotationGesture中的回调属性:
名称 | 说明 |
---|---|
angle | 旋转角度 |
fingerList | FingerInfo[],包含触发事件的所有触点信息 |
回调比较简单, 只需要在onActionUpdate中获取旋转角度用于计算就可以了。
接下来看一下控制组件旋转的rotate参数,只有angle是必填
名称 | 说明 |
---|---|
x | 旋转轴向量x坐标 |
y | 旋转轴向量y坐标 |
z | 旋转轴向量z坐标 |
angle | 旋转角度 |
centerX | 变换中心点x轴坐标 |
centerY | 变换中心点y轴坐标 |
centerZ | z轴锚点,即3D旋转中心点的z轴分量,px |
perspective | 相机放置的z轴坐标,px |
以上参数中,x,y,z 三个参数共同决定组件的旋转方向,例如
x:1, y:0, z:0:围绕 X 轴旋转(类似 “前后翻转”)
x:0, y:1, z:0:围绕 Y 轴旋转(类似 “左右翻转”)
x:0, y:0, z:1:围绕 Z 轴旋转(类似 “平面旋转”)
2D平面旋转中,centerX,centerY决定组件的旋转中心点,即以哪个点为中心旋转。
看一下旋转效果演示:
注意:
1.旋转过程中不会重新回调图片的onAreaChange,所以旋转中心点是基于图片初始状态的
2.centerZ测试不支持动态修改,感兴趣的可以自己赋值看一下效果
演示源码:
import { getScreenHeight, getScreenWidth } from '../utils/DisplayUtil'
@Extend(Radio)
function myRadioStyle() {
.checked(false)
.radioStyle({
checkedBackgroundColor: Color.Green, //开启状态底板颜色
uncheckedBorderColor:Color.Red, //关闭状态描边颜色
indicatorColor:Color.Yellow //开启状态内部圆饼颜色
})
.height(20)
.width(20)
}
@Entry
@ComponentV2
struct RotationGestureTest{
@Local imageWidth: number = getScreenWidth()
@Local imageHeight: number = getScreenHeight()
@Local imageTopleftX:number = 0 //图片左上角相对于父元素的坐标
@Local imageTopleftY:number = 0
@Local rotateValue :number=0 //旋转角度
@Local currentAngle :number=0 //记录当前旋转角度 用于旋转计算累加
@Local fingerList: FingerInfo[] = []
@Local rotateX:number = 0
@Local rotateY:number = 0
@Local rotateZ:number = 1
@Local rotateCenterX:number = 0 //旋转中心点 坐标
@Local rotateCenterY:number = 0
@Local centerX:number=50
@Local centerY:number=50
build() {
Column(){
Stack(){
Image($r('app.media.imagetest'))
.width(this.imageWidth)
.height(this.imageHeight)
.draggable(false)
.onComplete((event)=>{
const imageTrueWidth=event?.width??0
const imageTrueHeight=event?.height??0
// 宽度铺满
this.imageHeight = imageTrueHeight*this.imageWidth / imageTrueWidth;
})
.onAreaChange((oldValue: Area, newValue: Area)=>{
this.imageTopleftX = newValue.position.x as number
this.imageTopleftY = newValue.position.y as number
this.rotateCenterX = this.imageWidth/2
this.rotateCenterY = this.imageTopleftY+this.imageHeight/2
})
.rotate({
x:this.rotateX,y:this.rotateY,z:this.rotateZ,
centerX:this.centerX+'%',
centerY:this.centerY+'%',
angle:this.rotateValue})
.gesture(
RotationGesture({fingers:2,angle:5})
.onActionStart((event: GestureEvent) => {
})
.onActionUpdate((event: GestureEvent) => {
this.rotateValue = this.currentAngle + event.angle
})
.onActionEnd((event: GestureEvent) => {
this.currentAngle = this.rotateValue
})
)
Circle({width:20,height:20}).fill(Color.Red)
.position({
x:this.rotateCenterX,
y:this.rotateCenterY})
}.width('100%').height('50%').border({
width:2,
color:Color.Black
})
Column({space:20}){
Text('旋转角度:'+this.rotateValue).height(60).fontSize(24)
Button('恢复默认').onClick(()=>{
this.rotateValue=0
this.currentAngle=0
this.rotateX = 0
this.rotateY = 0
this.rotateZ = 1
this.rotateCenterX = this.imageWidth/2
this.rotateCenterY = this.imageTopleftY+this.imageHeight/2
this.centerX = 50
this.centerY = 50
})
Row(){
Radio({ value: 'x', group: 'radioGroup' })
.myRadioStyle()
.onChange((isChecked: boolean) => {
if(isChecked){
this.rotateX = 1
this.rotateY = 0
this.rotateZ = 0
}
})
Text('X轴方向旋转 ')
Radio({ value: 'y', group: 'radioGroup' })
.myRadioStyle()
.onChange((isChecked: boolean) => {
if(isChecked){
this.rotateX = 0
this.rotateY = 1
this.rotateZ = 0
}
})
Text('Y轴方向旋转 ')
Radio({ value: 'z', group: 'radioGroup' })
.myRadioStyle()
.checked(this.rotateZ==1)
.onChange((isChecked: boolean) => {
if(isChecked){
this.rotateX = 0
this.rotateY = 0
this.rotateZ = 1
}
})
Text('Z轴方向旋转 ')
}
Column(){
Row({ space: 10 }) {
Text('旋转中心点X偏移量' + this.centerX)
Slider({
value: this.centerX,
min: 0,
max: 100,
style: SliderStyle.OutSet
}).width('50%')
.onChange((value: number) => {
this.centerX = value;
this.rotateCenterX = this.imageWidth*this.centerX/100
})
}
Row({ space: 10 }) {
Text('旋转中心点Y偏移量' + this.centerY)
Slider({
value: this.centerY,
min: 0,
max: 100,
style: SliderStyle.OutSet
}).width('50%')
.onChange((value: number) => {
this.centerY = value;
this.rotateCenterY = this.imageHeight*this.centerY/100+this.imageTopleftY
})
}
Text('图片左上角坐标X'+this.imageTopleftX)
Text('图片左上角坐标Y'+this.imageTopleftY)
}
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.Gray)
}.layoutWeight(1).width('100%')
}
}
}