文章目录
大转盘 LuckyWheel 使用文档
安装
npm install luck-cmft --save
引用
import { LuckyWheel } from luck-cmft
使用
<template>
<div class="wrap">
<div id="wheel-test"></div>
</div>
</template>
let luckyWheel = new LuckyCanvas.LuckyWheel({
el: '#my-lucky',
width: '300px',
height: '300px',
}, {
// 参数
})
参数
背景 - blocks
blocks?: Array<object>
背景padding?: string
内边距 (为了保证大转盘是一个标准的圆, 所以 padding 只能输入一个值)background?: string
背景颜色 (可填写16进制颜色哈希值或 rgba)imgs?: Array<object>
图片列表 (新增)src: string
图片路径top?: string | number
距离顶部的高度 (可以写 20px 也可以是 20%,默认为 0)width?: string
图片宽度 (关于图片宽高有四种可能,如下)height?: string
图片高度 (关于图片宽高有四种可能,如下)rotate?: boolean
是否跟随旋转 (默认为 false)
1.宽高都未设置:则使用图片原大小;
2.有宽度无高度:则高度随着宽度等比缩放;
3.有高度无宽度:则宽度随着高度等比缩放;
4.既有宽度也有高度:则图片宽高均等于设置的值(会被拉伸)
关于绘制背景
- 第一个橘色的 block 的直径等于200px,等于父容器的宽
- 第二个红色的 block:直径等于180px,因为第一个 block 的padding上下左右同时挤出10px
- 第三个白色的 block:直径等于160px,因为第二个 block 的padding同样也挤出10px
- 最后白色 block 挤出的部分就是奖品区域了
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
/>
</template>
<script>
export default {
data () {
return {
blocks: [
{ padding: '10px', background: '#ffc27a' },
{ padding: '10px', background: '#ff4a4c' },
{ padding: '0px', background: '#fff' }
]
}
}
}
</script>
关于背景图
- rotate用来控制背景图是否跟随旋转, 默认为 false 不旋转
- 如果你的背景图里面就自带了奖品, 那你依然要控制好prizes的数量, 以及defaultConfig.offsetDegree, 因为我必须知道你有几个奖品才能准确的抽奖
- 理论上来说, 你可以仅凭一张背景图和一个按钮图片完成抽奖需求
<template>
<LuckyWheel
ref="LuckyWheel"
width="240px"
height="240px"
:blocks="blocks"
:prizes="prizes"
:buttons="buttons"
@start="startCallBack"
/>
</template>
<script>
export default {
data () {
return {
blocks: [
{ padding: '20px' },
{
padding: '20px',
imgs: [{
src: require('../examples/img/temp.png'),
width: '100%',
rotate: true
}]
}
],
prizes: [
{ name: '0' },
{ name: '1' },
{ name: '2' },
{ name: '3' },
{ name: '4' },
{ name: '5' },
{ name: '6' },
{ name: '7' },
],
buttons: [{
fonts: [{ text: 'Go', top: -12 }],
radius: '22%',
background: '#2da3e0',
pointer: true
}],
}
},
methods: {
startCallBack () {
this.$refs.LuckyWheel.play()
setTimeout(() => {
this.$refs.LuckyWheel.stop(Math.random() * 8 >> 0)
}, 1000)
},
}
}
</script>
奖品 - prizes
prizes?: Array<object>
奖品列表background?: string
扇形背景色 (可继承 defaultStyle 背景色,默认为 ‘rgba(0,0,0,0)’)fonts?: Array<object>
文字列表text: string
字体内容 (可以使用 \n 用来换行)top?: string | number
距离顶部的高度 (格式为:20 | ‘20px’ | ‘20%’,默认为 0)fontColor?: string
字体颜色 (可继承 defaultStyle 字体颜色,默认为 ‘#000’)fontSize?: string
字体大小(px) (可继承 defaultStyle 字体大小,默认为 ‘22px’)fontStyle?: string
字体样式 (可继承 defaultStyle 字体样式,默认为 ‘sans-serif’)fontWeight?: string
字体粗细 (可继承 defaultStyle 字体粗细,默认为 ‘400’)lineHeight?: string
字体行高 (默认等于字体大小)wordWrap?: boolean
文字自动换行 (默认为 true 开启,关闭时可以使用 \n 换行)lengthLimit?: string | number
换行宽度限制 (格式为:90 | ‘90px’ | ‘90%’,默认为 ‘90%’)
imgs?: Array<object>
图片列表src: string
图片路径top?: string | number
距离顶部的高度 (可以写 20px 也可以是 20%,默认为 0)width?: string
图片宽度 (关于图片宽高有四种可能,同上)height?: string
图片高度 (关于图片宽高有四种可能,同上)
关于设置奖品
- 奖品区域为扇形,会平分整个大转盘并以顺时针方向绘制,建议配置不同的背景色方便区分
- 文字默认以扇形的中线居中,会自动随着扇形的旋转而旋转
- 2号扇形的top为100%,所以他的文字超出了原本的区域
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
/>
</template>
<script>
export default {
data () {
return {
blocks: [{ padding: '10px', background: '#d64737' }],
prizes: [
{ fonts: [{ text: '0' }], background: '#f8d384' },
{ fonts: [{ text: '1', top: '20px' }], background: '#f9e3bb' },
{ fonts: [{ text: '2', top: '100%' }], background: '#fff' }
],
}
}
}
</script>
关于奖品文字换行
- 由于奖品是一个扇形区域,顶部的圆弧宽度计算困难,建议搭配top属性向下挤一部分
- wordWrap属性用来控制该段文字是否换行,默认为 true,但等于 false 时依然可以使用\n来换行
- lengthLimit属性用来控制自动换行的最大宽度,默认为’90%’
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
/>
</template>
<script>
export default {
data () {
return {
blocks: [
{ padding: '10px', background: '#d64737' },
],
prizes: [
{
fonts: [{ text: '当文字超长之后就会自动进行换行', top: 10, lengthLimit: '80%' }],
background: '#f8d384'
},
{
background: '#f9e3bb'
},
{
fonts: [{ text: '这段字不会自动换行', top: 20, wordWrap: false }],
background: '#f8d384'
},
{
background: '#f9e3bb'
}
],
}
}
}
</script>
关于配置图片
- 图片跟文字一样,会默认以扇形的中线居中
- 0号扇形的图片因为没有设置宽度或高度限制,所以他显示了图片的原本大小
- 1号扇形的图片只设置了宽度,那高度就会随着宽度进行等比缩放
- 2号扇形的图片同时设置了宽度和高度,所以他被拉伸了
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
/>
</template>
<script>
export default {
data () {
return {
blocks: [{ padding: '10px', background: '#d64737' }],
prizes: [
{ imgs: [{ src: require('../examples/img/1.png') }], background: '#f8d384' },
{ imgs: [{ src: require('../examples/img/1.png'), width: '30%' }], background: '#f9e3bb' },
{ imgs: [{ src: require('../examples/img/1.png'), width: '40%', height: '50%' }] }
],
}
}
}
</script>
抽奖按钮 - buttons
buttons?: Array<object>
抽奖按钮列表radius?: string
按钮半径pointer?: boolean
是否显示指针 (默认为 false)background?: string
按钮背景色 (可继承 defaultStyle 背景色,默认为 ‘#fff’)fonts?: Array<object>
文字列表text: string
字体内容 (可以使用 \n 用来换行)top?: string | number
距离顶部的高度 (格式为:20 | ‘20px’ | ‘20%’,默认为 0)fontColor?: string
字体颜色 (可继承 defaultStyle 字体颜色,默认为 ‘#000’)fontSize?: string
字体大小(px) (可继承 defaultStyle 字体大小,默认为 ‘22px’)fontStyle?: string
字体样式 (可继承 defaultStyle 字体样式,默认为 ‘sans-serif’)fontWeight?: string
字体粗细 (可继承 defaultStyle 字体粗细,默认为 ‘400’)lineHeight?: string
字体行高 (默认等于字体大小)
imgs?: Array<object>
图片列表src: string
图片路径top?: string | number
离圆心的距离 (格式为:20 | ‘20px’ | ‘20%’,默认为 0)width?: string
图片宽度 (关于图片宽高有四种可能,同上)height?: string
图片高度 (关于图片宽高有四种可能,同上)
关于配置按钮
- buttons的绘制顺序为从上到下,所以要注意半径的大小,以免下面的按钮过大,把后面的按钮覆盖掉
- pointer属性控制 item 是否显示指针,如果你想要一个炫酷的指针,那你可以通过引入 img 的方式来实现
- 我通常建议你在最后一个按钮里面绘制文字或图片,来避免被覆盖掉
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:buttons="buttons"
/>
</template>
<script>
export default {
data () {
return {
blocks: [
{ padding: '10px', background: '#d64737' },
{ padding: '0px', background: '#fff' },
],
buttons: [
{ radius: '40px', background: '#d64737' },
{ radius: '35px', background: '#f6c66f', pointer: true },
{
radius: '30px',
background: '#fff',
fonts: [{ text: '开始', top: '-13px' }]
}
],
}
}
}
</script>
关于按钮文字换行
- 按钮文字不会自动换行,没有wordWrap和lengthLimit属性
- 如果文字超出了按钮区域,你可以使用\n进行手动换行
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:buttons="buttons"
/>
</template>
<script>
export default {
data () {
return {
blocks: [
{ padding: '10px', background: '#d64737' },
{ padding: '0px', background: '#fff' },
],
buttons: [
{ radius: '40px', background: '#d64737' },
{ radius: '35px', background: '#f6c66f', pointer: true },
{
radius: '30px',
background: '#fff',
fonts: [
{ text: '开始\n抽奖', top: '-20px' },
{ text: '这是按钮文字', top: '20px' }
]
}
],
}
}
}
</script>
默认配置 - defaultConfig
defaultConfig?: object
默认配置gutter?: string | number
扇形之间的缝隙 (默认等于 0)stopRange?: number
扇形区域的停止范围 (默认为 0.8, 建议范围 0 ~ 0.9, 如果设置 1 可能会停在奖品边缘!)offsetDegree?: number
转盘的偏移角度 (默认为 0 度)speed?: number
旋转速度峰值 (默认为 20,建议配置范围 10 ~ 30)speedFunction?: string
缓动函数 (当前版本固定为 quadratic 二次方加速,后期会提供更多可选函数)accelerationTime?: number
开始旋转时间 (单位为毫秒,默认等于 2500 毫秒)decelerationTime?: number
缓慢停止时间 (单位为毫秒,默认等于 2500 毫秒)
关于奖品区域的缝隙
- gutter属性用来控制奖品扇形区域之间的缝隙,默认等于 0
- 这个缝隙是等距的,不会随着角度的不同而产生弧度
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
:buttons="buttons"
:default-config="defaultConfig"
/>
</template>
<script>
export default {
data () {
return {
blocks: [{ padding: '10px', background: '#d64737' }],
prizes: [
{ background: '#f8d384' },
{ background: '#f9e3bb' },
{ background: '#f8d384' },
{ background: '#f9e3bb' },
{ background: '#f8d384' },
{ background: '#f9e3bb' },
],
buttons: [{ radius: '30px', background: 'rgba(0, 0, 0, 0.1)' }],
defaultConfig: { gutter: '5px' }
}
}
}
</script>
关于转盘的偏移角度
- 建议配置的角度范围:-360 ~ 360
- 默认情况下,指针会指向扇形的中线,如果你想让其指向扇形的边缘,可以通过计算
- 比如这个转盘有 6 个奖品,那么每个扇形就等于360 / 6 = 60度,所以我只需要让转盘向前旋转60 / 2 = 30度即可
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
:buttons="buttons"
:default-config="defaultConfig"
/>
</template>
<script>
export default {
data () {
return {
blocks: [{ padding: '10px', background: '#d64737' }],
prizes: [
{ background: '#f8d384', fonts: [{ text: '0', top: 5 }] },
{ background: '#f9e3bb', fonts: [{ text: '1', top: 5 }] },
{ background: '#f8d384', fonts: [{ text: '2', top: 5 }] },
{ background: '#f9e3bb', fonts: [{ text: '3', top: 5 }] },
{ background: '#f8d384', fonts: [{ text: '4', top: 5 }] },
{ background: '#f9e3bb', fonts: [{ text: '5', top: 5 }] },
],
buttons: [
{ radius: '35px', background: '#d64737' },
{ radius: '30px', background: '#f6c66f', pointer: true },
{ radius: '25px', background: '#ffdea0' }
],
defaultConfig: {
gutter: '5px',
offsetDegree: 30
}
}
}
}
</script>
关于旋转速度
旋转总共分为三个阶段:
- 第一阶段进行加速旋转,速度会从 0 加速到speed设置的值(默认为20),加速曲线恒定的情况下,你设置的时间越短,加速度越大
- 第二阶段为匀速阶段,处于加速到峰值之后 && 调用stop方法之前,此时加速度恒定为speed
- 第三阶段会缓慢减速到停止,在你调用stop方法之后,速度会从speed逐渐降低到 0
注意:当你接口的请求速度,小于等于accelerationTime设置的毫秒值时,会跳过第二阶段,此时你可以手动加一个定时器延缓调用stop的时机,以此来留出匀速的时间
默认样式 - defaultStyle
defaultStyle?: object
格子默认样式fontColor?: string
字体颜色 (默认是 ‘#000’ 黑色)fontSize?: string
字体大小(px) (默认是 ‘18px’)fontStyle?: string
字体样式 (默认是 ‘sans-serif’)fontWeight?: string
字体粗细 (默认为 ‘400’)lineHeight?: string
字体行高 (默认等于字体大小)textAlign?: string
文字和图片的对其方式 (目前只能居中!)background?: string
奖品区域背景颜色 (默认是 ‘#fff’ 白色)wordWrap?: boolean
文字自动换行 (默认为 true 开启,关闭时可以使用 \n 换行)lengthLimit?: string | number
换行宽度限制 (格式为:90 | ‘90px’ | ‘90%’,默认为 ‘90%’)
- textAlign对其方式目前只支持 center
- background属性只有在奖品区域没有配置背景色时才会生效,但是按钮的背景色不会继承这里,而是显示透明色
<template>
<LuckyWheel
width="200px"
height="200px"
:blocks="blocks"
:prizes="prizes"
:default-style="defaultStyle"
/>
</template>
<script>
export default {
data () {
return {
blocks: [{ padding: '10px', background: '#d64737' }],
prizes: [
{ fonts: [{ text: '0' }], background: '#f8d384' },
{ fonts: [{ text: '1' }] },
{ fonts: [{ text: '2' }], background: '#f8d384' },
{ fonts: [{ text: '3' }] },
{ fonts: [{ text: '4' }], background: '#f8d384' },
{ fonts: [{ text: '5' }] },
],
defaultStyle: {
fontColor: 'red',
fontSize: '30px',
background: 'pink'
},
}
}
}
</script>
回调 & 方法
- strat?: Function 开始抽奖前 (当点击抽奖按钮时,触发该回调)
- end?: Function 抽奖结束后 (当九宫格完全停止时,触发该回调)
- play() 开始抽奖 (调用该方法时,游戏才会开始, 没有参数)
- stop(index) 缓慢停止抽奖 (调用该方法时,才会缓慢停止, 参数是中奖的索引;如果stop方法传入-1, 那游戏立即停止, 并且end回调不会触发)
<template>
<LuckyWheel
ref="LuckyWheel"
width="300px"
height="300px"
:prizes="prizes"
:default-style="defaultStyle"
:blocks="blocks"
:buttons="buttons"
@start="startCallBack"
@end="endCallBack"
/>
</template>
<script>
export default {
data () {
return {
prizes: [],
defaultStyle: {
fontColor: '#d64737',
fontSize: '14px'
},
blocks: [
{ padding: '13px', background: '#d64737' }
],
buttons: [
{ radius: '50px', background: '#d64737' },
{ radius: '45px', background: '#fff' },
{ radius: '41px', background: '#f6c66f', pointer: true },
{
radius: '35px', background: '#ffdea0',
imgs: [{ src: require('./img/button.png'), width: '65%', top: '-50%' }]
}
],
}
},
mounted () {
this.getPrizesList()
},
methods: {
getPrizesList () {
const prizes = []
let data = ['1元红包', '100元红包', '0.5元红包', '2元红包', '10元红包', '50元红包', '0.3元红包', '5元红包']
data.forEach((item, index) => {
prizes.push({
title: item,
background: index % 2 ? '#f9e3bb' : '#f8d384',
fonts: [{ text: item, top: '10%' }],
imgs:[{ src: require(`./img/${index}.png`), width: '30%', top: '35%' }],
})
})
this.prizes = prizes
},
startCallBack () {
this.$refs.LuckyWheel.play()
setTimeout(() => {
this.$refs.LuckyWheel.stop(Math.random() * 8 >> 0)
}, 3000)
},
endCallBack (prize) {
alert(`恭喜你获得${prize.title}`)
},
}
}
</script>