Commit ee648016 authored by wanghuan's avatar wanghuan

add:转盘

parent 1ae8dc89
import React,{useState, useEffect} from 'react'
import {View,Image,Text} from '@tarojs/components'
import styles from './RotateWheel.module.less'
import {useThrottle} from '@/hooks/useThrottle'
import API from '@/api'
import { prizeList } from '@/const'
import Taro,{showToast,redirectTo,navigateTo} from '@tarojs/taro'
const oneTurn = 360;
const RotateWheel = (props) => {
const {
bg,
ratio,
radius,
circles,
divideNum,
duration,
timeFunction,
nodeInfo,
showWay,
isShowPrizeName
} = props;
/* 奖品列表 */
const [prizelist,setPrizelist] = useState(prizeList)
/* 平分角度 */
const [angle,setAngle] = useState(oneTurn / divideNum)
/* my.createAniamation */
const [myAnimation,setMyAnimation] = useState()
/* 展示奖品列表 */
const [show,setShow] = useState(false)
/* 转动一圈时的角度值 */
const [rotateInOneTurn,setRotateInOneTurn] = useState(0)
/* 动画参数 */
const [ani,setAni] = useState({startFlag:false,option:{duration:duration,timeFunction:timeFunction,rotate:0}})
useEffect(()=>{
computePosition()
},[])
/**
* @description 计算奖品位置,旋转角度
*/
const computePosition = () => {
let centerX,centerY,color,rotate;
/* 获取每块奖品的中心位置 */
prizelist.forEach((ele, i)=>{
if (i % 2 == 0) {
color = '#527aff';
} else {
color = '#f13082'
}
// 当前奖品左上角位置
if(showWay === 'negative'){
centerX = radius - ratio * radius * (Math.sin((angle / 2 + angle * (i)) / 180 * Math.PI));
centerY = radius - ratio * radius * (Math.cos((angle / 2 + angle * (i)) / 180 * Math.PI));
rotate = -(angle / 2 + angle * i);
} else {
centerX = radius - ratio * radius * (Math.sin((angle / 2 + angle * (-i)) / 180 * Math.PI));
centerY = radius - ratio * radius * (Math.cos((angle / 2 + angle * (-i)) / 180 * Math.PI));
// 旋转角度
rotate = -(angle / 2 + angle * (-i));
}
ele.rotate = rotate
ele.color = color
// 奖品位置
let disleft = centerX - nodeInfo.width / 2;
let distop = centerY - nodeInfo.height / 2;
ele.centerX = disleft
ele.centerY = distop
ele.num = i;
// 测试:设置奖品Id
ele.prizeId = 100 + i;
})
console.log('prizelist',prizelist);
setPrizelist(prizelist)
setShow(true)
}
/**
* @description 抽奖
*/
const drawPrize = useThrottle( async() => {
// const {success,data,message,code} = await API.drawLotteryPrize().catch((res)=>{
// showToast(res?.message ? res?.message : '')
// });
// if(success && data){
// }
let prizeId = Math.floor(Math.random() * prizelist.length) + 100;
startRotation(prizeId)
},duration)
/**
* @description 根据奖品id开始旋转
* @param {*} prizeId 抽中的奖品id
*/
const startRotation = (prizeId) => {
console.log('start');
let rotateAngle;
let num;
let oneturnAngle;
prizelist.forEach((ele)=>{
if(ele.prizeId === prizeId){
num = ele.num;
}
})
// 旋转角度 ( 旋转圈数 + 对应位置(0,7) ) * 平分角度 + 平分角度 / 2
if(showWay === 'negative'){
rotateAngle = oneTurn * circles + num * angle + angle / 2;
oneturnAngle = num * angle + angle / 2;
} else {
rotateAngle = oneTurn * circles + (prizelist.length - num) * angle + angle / 2;
oneturnAngle = (prizelist.length - num) * angle + angle / 2
}
console.log('rotateAngle',rotateAngle, num, prizeId);
/* 执行动画 */
setAni({
startFlag:true,
option:{
...ani.option,
rotate:ani.option.rotate - rotateInOneTurn + rotateAngle
}
})
setRotateInOneTurn(oneturnAngle)
}
// my.createAnimation 旋转动画rot:旋转角度,timegap:旋转时间
// const animateRotation = (rot, timegap) => {
// var animation = my.createAnimation({
// transformOrigin: "center center",
// duration: 5000,
// timeFunction: "ease-out",
// delay: 0
// })
// console.log('animation',animation);
// animation.rotate(rot).step();
// setMyAnimation(animation.export())
// setTimeout(() => {
// setMyAnimation()
// }, 5000);
// }
return(
<>
<View className={`${styles['rotate_container']}`}
style={{
backgroundImage:`url(${bg})`,
transform:ani.startFlag ? `rotate(${ani.option.rotate}deg)` : '',
transition:ani.startFlag ? `all ${ani.option.timeFunction} ${ani.option.duration}ms` : ''
}}
// animation={myAnimation}
>
{
show && prizelist.length && prizelist.map((ele, i)=>{
return(
<View
className={styles['item']}
style={{
backgroundColor:`${ele?.color}`,
width:`${nodeInfo.width/100}rem`,
height:`${nodeInfo.height/100}rem`,
transform:`rotate(${ele?.rotate}deg)`,
top:`${ele.centerY/100}rem`,
left:`${ele.centerX/100}rem`,
position:'absolute'
}}
key={'item'+i}>
{
isShowPrizeName &&
<View
className={styles['prize_name']}
style={{width:'90%',height:`${30/100}rem`}}
>奖品名称奖品名称{i}</View>
}
<View className={styles['prize_img']}
style={{
backgroundImage:`url(${ele.image})`,
width:`${80/100}rem`,
height:`${80/100}rem`
}}
></View>
</View>
)
})
}
</View>
<View className={styles['circle']} onTap={drawPrize}>draw</View>
</>
)
}
export default RotateWheel
\ No newline at end of file
.rotate_container{
width: 100%;
height: 100%;
border: 1px solid cyan;
box-sizing: border-box;
position: relative;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.image-property(cover, center center);
.item{
position: absolute;
display: flex;
justify-content: space-evenly;
align-items: center;
transform-origin: center;
flex-direction: column;
border: 1px solid cyan;
box-sizing: border-box;
.prize_name{
margin: 0 auto;
border: 1px solid cyan;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
white-space: nowrap;
font-size: 18px;
}
.prize_img{
.image-property(cover, center center);
margin: 0 auto;
}
}
}
.circle{
// border-radius: 50%;
width: 100px;
height: 100px;
background-color: rgb(78, 159, 165);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
clip-path: polygon(50% 0%,0% 100%,100% 100%);
}
<mxfile host="65bd71144e">
<diagram id="aWOBYljMTH3HiLopJFIH" name="第 1 页">
<mxGraphModel dx="899" dy="594" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="3" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;shadow=1;fillColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="200" y="160" width="300" height="300" as="geometry"/>
</mxCell>
<mxCell id="6" value="" style="endArrow=none;dashed=1;html=1;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="310" as="sourcePoint"/>
<mxPoint x="500" y="310" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="8" value="" style="endArrow=none;dashed=1;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fillColor=#FF9999;" edge="1" parent="1" source="3" target="3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="430" y="330" as="sourcePoint"/>
<mxPoint x="480" y="280" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="9" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="379" y="210" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="10" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="379" y="340" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="11" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="250" y="210" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="12" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="250" y="340" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="13" value="1.找到每个奖品的中心位置&lt;br&gt;2.每个奖品旋转相应角度&lt;br&gt;3.给相应的奖品区域设置样式" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;shadow=0;" vertex="1" parent="1">
<mxGeometry x="490" y="180" width="250" height="50" as="geometry"/>
</mxCell>
<mxCell id="16" value="旋转逻辑" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;strokeColor=#000000;fillColor=#FFCCCC;" vertex="1" parent="1">
<mxGeometry x="80" y="510" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="17" value="给每个奖品设置一个索引值,抽中的奖品id与奖品列表对应,则根据索引值旋转对应的角度。" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;shadow=0;" vertex="1" parent="1">
<mxGeometry x="80" y="590" width="200" height="110" as="geometry"/>
</mxCell>
<mxCell id="18" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;shadow=0;strokeColor=#000000;fillColor=#FFCCCC;" vertex="1" parent="1">
<mxGeometry x="310" y="270" width="80" height="80" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
\ No newline at end of file
**记事本打开**
#### 大转盘配置项入参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| bg | String | 转盘背景 | / | / |
| radius | Number | 转盘半径大小 | 300 | px |
| ratio | Number | 距离中心点的比例系数 | 0.65 | 小于1 |
| divideNum | Number | 转盘划分为几等分 | 8 | 最少2等分|
| circles | Number | 转盘基本转动圈数 | 4 | / |
| duration | Number | 转盘持续时间 | 4000 | 毫秒 |
| timeFunction | String | 缓动动画方式 | 'ease-out' | TODO其他类型待补充 |
| nodeInfo | Object | 单个奖品区域大小 | {width:100,height:100} | 宽高各100px |
| showWay | String | 奖品排列方式 | 'negative' |negative逆时针排列 positive顺时针排列|
| isShowPrizeName | Boolean | 是否展示奖品名称 | true | true展示 false不展示 |
<!-- | showNameMaxLength | Number | 奖品名称长度展示限制 | 8 | / | -->
......@@ -146,35 +146,55 @@ export const CLOUD_OBJ = {
export const prizeList = [
{
image:
"//yun.duiba.com.cn/spark/assets/240121a7e7e10a66ad0cfa99a8b3ba9631fc7855.png",
"https://yun.duiba.com.cn/spark/assets/240121a7e7e10a66ad0cfa99a8b3ba9631fc7855.png",
name:'商品描述商品描述商品描述商品描述商品描述1',
content:'商品描述商品描述商品描述商品描述商品描述1',
},
{
image:
"//yun.duiba.com.cn/spark/assets/f9160b053f525455503ea58ae6b43bacea400362.png",
"https://yun.duiba.com.cn/spark/assets/f9160b053f525455503ea58ae6b43bacea400362.png",
name:'商品描述商品描述商品描述商品描述商品描述2',
content:'商品描述商品描述商品描述商品描述商品描述2'
},
{
image:
"//yun.duiba.com.cn/spark/assets/28b868b5da81ebd28a4eb14291a8ac287937221c.png",
"https://yun.duiba.com.cn/spark/assets/28b868b5da81ebd28a4eb14291a8ac287937221c.png",
name:'商品描述商品描述商品描述商品描述商品描述3',
content:'商品描述商品描述商品描述商品描述商品描述3'
},
{
image:
"//yun.duiba.com.cn/spark/assets/3c305fb907bbebb85ad392cb959fbe62200c407f.png",
"https://yun.duiba.com.cn/spark/assets/3c305fb907bbebb85ad392cb959fbe62200c407f.png",
name:'商品描述商品描述商品描述商品描述商品描述4',
content:'商品描述商品描述商品描述商品描述商品描述4'
},
{
image:
"//yun.duiba.com.cn/spark/assets/554a90eee5a31ae7628950907974bdee2da8c01e.png",
"https://yun.duiba.com.cn/spark/assets/28b868b5da81ebd28a4eb14291a8ac287937221c.png",
name:'商品描述商品描述商品描述商品描述商品描述5',
content:'商品描述商品描述商品描述商品描述商品描述5'
},
{
image:
"https://yun.duiba.com.cn/spark/assets/3c305fb907bbebb85ad392cb959fbe62200c407f.png",
name:'商品描述商品描述商品描述商品描述商品描述6',
content:'商品描述商品描述商品描述商品描述商品描述6'
},
{
image:
"https://yun.duiba.com.cn/spark/assets/554a90eee5a31ae7628950907974bdee2da8c01e.png",
name:'商品描述商品描述商品描述商品描述商品描述7',
content:'商品描述商品描述商品描述商品描述商品描述7'
},
{
image:
"https://yun.duiba.com.cn/spark/assets/554a90eee5a31ae7628950907974bdee2da8c01e.png",
name:'商品描述商品描述商品描述商品描述商品描述8',
content:'商品描述商品描述商品描述商品描述商品描述8'
}
];
\ No newline at end of file
......@@ -23,6 +23,8 @@ import ScrollXView from '@/components/_tb_comps/ScrollXView/ScrollXView'
import SwiperView from '@/components/_tb_comps/SwiperView/SwiperView'
import RotateWheel from '@/components/_tb_comps/RotateWheel/RotateWheel'
const INDEX_CONFIG = {
bg: '', // 背景 cloud://C4015B7CEC23CF013A78247E2852524F//火箭待机小球抖动.json
ruleButton: '', // 规则按钮
......@@ -31,6 +33,22 @@ const INDEX_CONFIG = {
taskButton: '' // 任务按钮
}
const rotateConfig = {
bg: 'https://yun.duiba.com.cn/spark/assets/8b6e920ffd09fab8f9ac2de09f9154879f4d0607.png',
ratio: 0.65,
radius: 300,
circles: 4,
divideNum: 8,
duration: 5000,
timeFunction:'ease-out',
nodeInfo:{
width:100,
height:100
},
showWay:'negative',//positive/negative
isShowPrizeName:true
}
function Index() {
......@@ -50,7 +68,7 @@ function Index() {
const showHelp = useRef(false)
/* 背景音乐 */
const {playAudio,musicUrl,setOpenStatus,openStatus} = useAudio(BGMUSIC_URL.MUSIC,true)
// const {playAudio,musicUrl,setOpenStatus,openStatus} = useAudio(BGMUSIC_URL.MUSIC,true)
......@@ -69,18 +87,18 @@ function Index() {
success && setUserInfo(data)
}
useEffect(() =>{
fetchActivityInfo()
getImgShareUrl('cloud://CEFE74AE67921906B5AF842150646D35/share.png').then(url => {
SHARE_IMG.current = url
})
// fetchActivityInfo()
// getImgShareUrl('cloud://CEFE74AE67921906B5AF842150646D35/share.png').then(url => {
// SHARE_IMG.current = url
// })
},[])
// 授权登录完成
useLogin(async (info) => {
handleVisibleModal(info)
fetchUserInfo()
setUpdateFlag(1)
getShareInfo()
})
// useLogin(async (info) => {
// handleVisibleModal(info)
// fetchUserInfo()
// setUpdateFlag(1)
// getShareInfo()
// })
// 查看是否有助力信息
const getShareInfo = async () => {
const { success, data } = await API.getShareInfo()
......@@ -171,7 +189,20 @@ function Index() {
{/* <ScrollXView prizeList={prizeList} /> */}
{/* swiper左右滑动 */}
<SwiperView swiperList={prizeList} vertical={false} disableTouch={true} />
{/* <SwiperView swiperList={prizeList} vertical={false} disableTouch={true} /> */}
{/* 大转盘 */}
<View className={styles['rotate']}
style={{
width:`${600/100}rem`,
height:`${600/100}rem`,
margin:`${100/100}rem auto`,
display:'flex',
justifyContent:'center',
alignItems:'center'
}} >
<RotateWheel {...rotateConfig} />
</View>
{
tasksModalVisible &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment