HarmonyOS 滚动式选中交互示例?

具体交互示例:支持读取标签数据&数值;支持自行滚动、拖拽滑动、点击等交互。

阅读 526
1 个回答

参考示例:

import { promptAction } from '@kit.ArkUI'

@Entry
@Component
export  struct Page248191 {
  radiusValue:number = 100
  angleX:number = Math.PI / 300
  angleY:number = Math.PI / 300
  centerX:number = 170
  centerY:number = 150
  timerAn:number = 0
  speedTimer:number = 0
  @State positionX: number = 0
  @State positionY: number = 0
  viewStartX:number = Math.PI / 300
  viewStartY:number = Math.PI / 300
  @State dataItemArray: TagsInfo[] = [
    new TagsInfo("12","",12, 1, 10, 10, 1),
    new TagsInfo("1","",12, 1, 10, 10, 1),
    new TagsInfo("都","",12, 1, 10, 10, 1),
    new TagsInfo("1","",12, 1, 10, 10, 1),
    new TagsInfo("rew","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("17","",12, 1, 10, 10, 1),
    new TagsInfo("12","",12, 1, 10, 10, 1),
    new TagsInfo("13","",12, 1, 10, 10, 1),
    new TagsInfo("14","",12, 1, 10, 10, 1),
    new TagsInfo("15","",12, 1, 10, 10, 1),
    new TagsInfo("16","",12, 1, 10, 10, 1),
  ];
  //绕x轴转
  rotateX(){
    let  cos = Math.cos(this.angleX);
    let  sin = Math.sin(this.angleX);
    this.dataItemArray.forEach((item) => {
      let y = (item.y - this.centerY)* cos - item.z * sin + this.centerY
      let z = item.z * cos + (item.y - this.centerY) * sin;
      item.y = y;
      item.z = z;
      item.itemAlpha = (item.z + this.radiusValue) / (2 * this.radiusValue)
    })
  }
  //绕Y轴转
  rotateY() {
    let cos = Math.cos(this.angleY);
    let sin = Math.sin(this.angleY);
    this.dataItemArray.forEach((item)=> {
      let x = (item.x - this.centerX) * cos - item.z * sin + this.centerX
      let z = item.z * cos + (item.x - this.centerX) * sin;
      item.x = x;
      item.z = z;
      item.itemAlpha = (item.z + this.radiusValue) / (2 * this.radiusValue)
    })
  }
  //随机颜色
  getRandomColor ():string{
    return '#'+(Math.random()*0xffffff<<0).toString(16);
  }
  //手势改变旋转方向和速度
  listener (event:GestureEvent) {
    let x = -event.offsetX
    let y = -event.offsetY
    let changeX = x * 0.0001 > 0 ? Math.min(this.radiusValue * 0.002 , x * 0.001 ) : Math.max(-this.radiusValue * 0.002, x * 0.001);
    let changeY =  y * 0.0001 > 0 ? Math.min(this.radiusValue * 0.002 , y * 0.001) : Math.max(-this.radiusValue * 0.002, y * 0.001);

    if (changeX != 0 && changeY != 0) {
      this.angleY = changeX
      this.angleX = changeY
    }
    this.rotateX();
    this.rotateY();
  }
  timerAnAction(){
    if (this.timerAn) {
      clearInterval(this.timerAn)
    }else {
      this.timerAn = setInterval(() => {
        this.rotateX();
        this.rotateY();
      },17)
    }
  }

  aboutToAppear(): void {
    //改变 每个item的位置
    for (let i = 0; i < this.dataItemArray.length; i++) {
      let a:number, b:number;
      let k = -1 + (2 * (i + 1) - 1) / this.dataItemArray.length;
      a = Math.acos(k);
      b = a * Math.sqrt(this.dataItemArray.length * Math.PI);

      let item = this.dataItemArray[i]
      item.x = this.radiusValue * Math.sin(a) * Math.cos(b) + this.centerX
      item.y = this.radiusValue * Math.sin(a) * Math.sin(b) + this.centerY
      item.z = this.radiusValue * Math.cos(a)
      item.nameTitle = "测试"+i
      item.fontSizeCount = 10
      item.itemColor = this.getRandomColor()
      item.itemAlpha = (item.z + this.radiusValue) / (2 * this.radiusValue)
    }
    //定时器旋转
    this.timerAnAction()
  }
  build() {
    Row() {
      Column(){
        ForEach(this.dataItemArray, (item:TagsInfo) => {
          tagView({tagsInfo:item})
        }, (item:TagsInfo) => JSON.stringify(item))
      }
      .height(300)
      .width("100%")
      .onTouch((event?: TouchEvent)=>{
        if(event){
          if (event.type === TouchType.Down) {
            clearInterval(this.timerAn)
          }
          if (event.type === TouchType.Up) {
            this.timerAn = setInterval(() => {
              this.rotateX();
              this.rotateY();
            },17)
          }
        }
      })
      .gesture(
        PanGesture().onActionStart((ev)=>{
          if (this.speedTimer) {
            clearInterval(this.speedTimer)
            this.speedTimer = null
          }
        }).onActionEnd((ev)=>{
          this.speedTimer = setInterval(()=>{
            if (Math.abs(this.angleX) * 0.7 > this.viewStartX || Math.abs(this.angleY) * 0.7 > this.viewStartY) {
              this.angleX = this.angleX * 0.7
              this.angleY = this.angleY * 0.7
            }else {
              clearInterval(this.speedTimer)
              this.speedTimer = null
            }
          },500)
          clearInterval(this.timerAn)
          this.timerAn = setInterval(() => {
            this.rotateX();
            this.rotateY();
          },17)

        }).onActionUpdate((ev)=>{
          this.listener(ev)
        })
      )
    }
    .height(300)
    .width("100%")
  }
}

@Component
export  struct tagView {
  @ObjectLink tagsInfo: TagsInfo
  build() {
    Text(this.tagsInfo.nameTitle)
      .fontSize(this.tagsInfo.fontSizeCount)
      .fontColor(this.tagsInfo.itemColor)
      .position({
        x:this.tagsInfo.x,
        y:this.tagsInfo.y,
      })
      .opacity(this.tagsInfo.itemAlpha)
      .onClick((ev)=>{
        promptAction.showToast({message:this.tagsInfo.nameTitle})
      })

  }
}

@Observed
class TagsInfo {
  x:number=0;
  y:number=0;
  z:number = 0;
  nameTitle:string = ""
  fontSizeCount:number = 0
  itemAlpha:number = 0
  itemColor:string = ""
  constructor(title:string,color:string,fontSizeCount:number,alpha:number, x:number, y:number, z:number) {
    this.nameTitle = title;
    this.itemColor = color
    this.fontSizeCount = fontSizeCount
    this.itemAlpha = alpha
    this.x = x;
    this.y = y;
    this.z = z;
  }
}