uniapp 用view画抽奖转盘
实现思路:
因为是画转盘,而不是画扇形,所以可以绕过用view画扇形,直接画一个圆,然后画几条直径,把文字写入的时候旋转一下就可以了。
以6等分为例,实现步骤:
- 画转盘背景:
- 画一个圆,填充背景颜色;
- 用“子绝父相”布局,画一条直径,垂直居中;
- 再画一条直径,旋转60度;
- 画第三条直径,旋转120度;
- 在转盘背景上写文字:
- 以圆的外接矩形为外层容器,设置绝对布局和flex布局水平居中;
- 内层view设置绝对布局,写入数据;
- 由于绝对布局和外层容器设置了水平居中,所有的内层view都堆在中心,水平居中;
- 以中心为旋转点,内层view分别旋转 -60度、-120度;-180度、-240度、-300度;
- 设置文字方向垂直,写入完成;
- 画转盘上指针:
- 样式可以自定义。
- 增加旋转动画。
实现效果:
具体代码如下(添加了禁止连续点击多次):
<!-- 抽奖转盘 --> <template> <view id="app"> <view class="title">{{showTextList[result].title}}</view> <view class="container" @click="startLottery" :style="{ top: windowSize.height * 0.05 + 'px' }"> <!-- 转盘 --> <view class="circle" :animation="animationData"> <view class="lines"> <view v-for="(item, index) in lineList" :style="{ transform: 'rotate(' + item.rotateDeg + 'deg)' }"> </view> </view> <view class="texts"> <view v-for="(item, index) in showTextList" :style="{ transform: 'rotate(' + item.rotateDeg + 'deg)' }"> {{ item.title }} </view> </view> </view> <!-- 指针 --> <view class="pointer"> <view class="pointer-triangle" :style="{ borderBottomWidth: windowSize.width / 14 + 'px', borderRightWidth: windowSize.width / 30 + 'px', borderLeftWidth: windowSize.width / 30 + 'px', }"></view> <view class="pointer-circle" :style="{ width: windowSize.width / 12 + 'px', height: windowSize.width / 12 + 'px', }">GO</view> </view> </view> </view> </template> <script> export default { data() { return { windowSize: {}, lineList: [], showTextList: [], isClicked: false, animationData: {}, lastResult: 0, result: 0, deg: 0, }; }, onLoad() { this.initData(); }, mounted() { this.windowSize = this.getWindowSize(); }, methods: { /* 获取屏幕可用尺寸 */ getWindowSize() { const windowInfo = uni.getWindowInfo(); let availableWindowSize = { width: 0, height: 0 }; availableWindowSize.width = windowInfo.windowWidth; //px availableWindowSize.height = windowInfo.windowHeight; //px // console.log("windowSize", this.windowSize); return availableWindowSize; }, // 初始化数据 initData() { this.lineList = [{ rotateDeg: 0, }, { rotateDeg: 60, }, { rotateDeg: 120, }]; // 文字要逆时针旋转 this.showTextList = [{ title: "1:跑步", rotateDeg: 0 }, { title: "2:游泳", rotateDeg: -60 }, { title: "3:666", rotateDeg: -120 }, { title: "4:打拳", rotateDeg: -180 }, { title: "5:剑道", rotateDeg: -240 }, { title: "6:play piano", rotateDeg: -300 } ]; }, /* 开始旋转抽奖 */ startLottery() { if (this.isClicked) { //已经点击了 console.log("点击太频繁啦"); return; } this.isClicked = true; let animation = uni.createAnimation({ transformOrigin: "50% 50%", duration:2000, timingFunction: "ease-in-out", delay: 0, }); this.animationData = animation; this.animationData.rotate(this.randomNum()).step(); this.animationData = this.animationData.export(); setTimeout(() => { this.isClicked = false; }, 2000); }, /* 获取随机数 */ randomNum() { this.result = Math.floor(Math.random() * 6); //数组索引:[0,5] if (this.result > this.lastResult) { this.deg += 360 * 4 + (this.result - this.lastResult) * 60; } else { this.deg += 360 * 4 + 360 - (this.lastResult - this.result) * 60; } // console.log(`result:${this.result},deg:${this.deg}`); this.lastResult = this.result; return this.deg; }, }, }; </script> <style scoped> .title{ text-align: center; } .container { position: relative; width: 100%; /* background: rgba(87, 189, 106, 0.5); */ border: 1rpx solid skyblue; } .circle { position: relative; margin: auto; width: 400rpx; height: 400rpx; border-radius: 50%; border: 20rpx solid goldenrod; background: rgba(0, 112, 46, 0.8); } .lines { position: absolute; width: 100%; height: 100%; left: 0; top: 0; display: flex; justify-content: center; align-items: center; } .lines>view { display: inline-block; width: 100%; height: 1%; position: absolute; transform-origin: center center; background-color: #f5b362; } .texts { position: absolute; width: 100%; height: 100%; top: 0; left: 0; display: flex; justify-content: center; } .texts view { display: inline-block; height: 96%; color: white; position: absolute; writing-mode: vertical-lr; transform-origin: center center; /* background-color: #bd2d30; */ } .pointer { position: absolute; margin: auto; width: 100%; height: 100%; top: 0; left: 0; /* border: 5rpx solid yellow; */ } .pointer-triangle, .pointer-circle { position: absolute; z-index: 1; left: 50%; top: 50%; transform: translate(-50%, -50%); display: inline-block; } .pointer-triangle { width: 0; height: 0; border-style: solid; border-top-width: 0px; border-color: transparent transparent #bd2d30 transparent; transform: translate(-50%, -100%); } .pointer-circle { display: flex; justify-content: center; align-items: center; border-radius: 50%; color: white; font-weight: bold; background: #bd2d30; } </style>