鸿蒙NEXT如何实现转盘抽奖功能

引言

身为一个前端开发,老板说让我去学鸿蒙开发
好好好 这么好的机会我不得好好抓住,我要去榨干鸿蒙开发同事的所有精华!!!
说干就干

需求

实现抽奖转盘转转转,
在这里插入图片描述

技术

我们就是代码的搬运工,ctrl+c 和ctrl+v是我们的吃饭技术,没到绝境是不可能用canvas直接手写的,更何况是我这种新手鸿蒙开发

上道具
开发工具:DevEco Studio
语言:ArkTS、ArkUI
插件工具:mpchart【openHarmony三方库中心仓】

开发三部曲

安装插件

ohpm install @ohos/mpchart

使用插件

1 引入相关依赖

import {
  ChartColor,
  ColorTemplate,
  JArrayList,
  MPPointF,
  PieChart,
  PieChartModel,
  PieData,
  PieDataSet,
  PieEntry,
} from '@ohos/mpchart';
import animator, { AnimatorOptions, AnimatorResult } from '@ohos.animator';

2 界面展示-自定义

// 转盘显示
      Row(){
        Stack() {
          Image($r('app.media.turn_table'))
            .height('100%')
          PieChart({ model: this.model })//转盘渲染在这里
            .height('82%')
            .aspectRatio(1)

          Row(){
            Stack(){
              Image($r('app.media.turn_start'))
                .width('80vp')
                .height('80vp')

              Text('开始')
                .fontSize('14fp')
                .fontColor(Color.White)
                .margin({top:'14vp'})
            }
          }
          .onClick(() => {
            this.startGun();
          })
        }
      }.height(380)

3 初始化转盘

@State model: PieChartModel = new PieChartModel();
@State animatorResult: AnimatorResult | null = null
@State onePartAngle: number = 0;//一扇的角度
@State totalCount:number = 0;//所有比值总和
//数据定义
@State parties:OptionSetting[]=[
    new OptionSetting('麻辣火锅',1),
    new OptionSetting('意大利披萨',1),
    new OptionSetting('日式寿司',1),
    new OptionSetting('中式快餐',1),
    new OptionSetting('韩国烤肉',1),
    new OptionSetting('素食沙拉',1),
  ]
@State count:number = this.parties.length 

init() {
    this.model.getDescription()?.setEnabled(false);
    this.model.setDrawHoleEnabled(false);
    this.model.getLegend()?.setEnabled(false);
    this.model.disableScroll();
    this.model.setHighlightPerTapEnabled(false);
    this.model.setEntryLabelTextSize(14)
    this.model.setEntryLabelColor(ColorTemplate.rgb('#606266'))
    this.model.setTouchEnabled(true);
    this.model.setRotationAngle(0);  // 设置旋转角度
    this.model.setUsePercentValues(true);  // 使用百分比值
    this.model.setDrawCenterText(true);  // 绘制中心文本
    // 通过触摸启用图表的旋转
    this.model.setRotationEnabled(true);
    this.setData(this.count);
  }
  // 初始化饼状图数据
  async setData(range: number): Promise<void> {
    let entries: JArrayList<PieEntry> = new JArrayList<PieEntry>();
    // 先计算总和
    for (let i = 0; i < this.count; i++) {
      this.totalCount  = this.totalCount + Number(this.parties[i].weight)
    }
    // NOTE: The order of the entries when being added to the entries array determines their position around the center of
    // the chart.
    for (let i = 0; i < this.count; i++) {
      entries.add(new PieEntry( Number(this.parties[i].weight)*(360 / this.totalCount),this.parties[i].textVal,undefined,undefined));
    }

    let dataSet: PieDataSet = new PieDataSet(entries, "Election Results");
    dataSet.setSliceSpace(0);
    dataSet.setIconsOffset(new MPPointF(0, 40));
    dataSet.setSelectionShift(5);
    dataSet.setValueTextSize(12)
    dataSet.setValueTextColor(ColorTemplate.rgb('#a8abb2'));
    dataSet.setDrawValues(false);
    // add a lot of colors
    let colors: JArrayList<number> = new JArrayList();
    for (let index = 0; index < ColorTemplate.COLORFUL_COLORS.length; index++) {
      colors.add(ColorTemplate.COLORFUL_COLORS[index]);
    }
    // colors.add(ColorTemplate.getHoloBlue());
    dataSet.setColorsByList(colors);
    let data: PieData = new PieData(dataSet);
    this.onePartAngle = 360 / this.totalCount;//一扇的角度
    // this.model.setRotationAngle(-90 - this.onePartAngle / 2);
    this.model.setData(data);
  }

4 滚动操作

startGun() {
	 let chooseText = ''
    let currentAngle = this.model.getRotationAngle(); //获取当前角度
    let randomIndex: number = Math.floor(Math.random() * this.count);
    let end = 7200 + randomIndex * currentAngle  +  this.onePartAngle;  //随机生成滚动结束角度
    let options: AnimatorOptions = {
      duration: 5000,
      easing: "ease",
      delay: 0,
      fill: "forwards",
      direction: "normal",
      begin: currentAngle,
      end: end,
      iterations: 1
    };
    this.animatorResult = animator.create(options)
    this.animatorResult.onframe = (value) => {
      this.model.setRotationAngle(value);
      this.model.invalidate();
    }
    //滚动结束
    this.animatorResult.onfinish = () => {
      let endAngle = this.model.getRotationAngle()
      // 渲染角度 
      for (let i = 0; i < this.parties.length; i++) {
        const element = this.parties[i];
        if(i==0){//算出第一个位置
          element.angleX = Math.floor(endAngle*i + endAngle)
        }else {
          element.angleX =  Number(this.parties[i-1].angleY)==360?0:Number(this.parties[i-1].angleY)
        }
        let RotateCicle:number = (element.angleX + this.onePartAngle * Number(element.weight))%360
        element.angleY = (element.angleX + this.onePartAngle * Number(element.weight)) >= 360?RotateCicle :Math.floor((element.angleX + this.onePartAngle * Number(element.weight)))
        if(element.angleX < element.angleY) {
          if(270 >= element.angleX && 270 < element.angleY){
            chooseText = element.textVal;
            break;
          }
        }else {
          if(270 >= element.angleX){
            chooseText = element.textVal;
            break;
          }
        }
      }
      if (this.dialogController != null) {
        this.textValue = chooseText //获取到选中的值
        this.dialogController.open()
      }
    }
    this.animatorResult.play();
  }
完成

选中的内容,大家可以定义一个弹框弹出即可

总结

是不是简简单单,老板叫我干啥我干啥,这点需求不在话下,可以找老板涨工资啦!!!
冲冲冲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值