init
This commit is contained in:
45
uni_modules/nutui-uni/components/dollmachine/dollmachine.ts
Normal file
45
uni_modules/nutui-uni/components/dollmachine/dollmachine.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { CLICK_EVENT } from '../_constants'
|
||||
import { commonProps, makeArrayProp, makeNumberProp } from '../_utils'
|
||||
|
||||
export const dollmachineProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 初始化爪子的图片链接
|
||||
*/
|
||||
defaultClaw: {
|
||||
type: String,
|
||||
default:
|
||||
'https://img14.360buyimg.com/imagetools/jfs/t1/146467/34/22553/4178/61b088afE198f676e/21952e7018d1d141.png',
|
||||
},
|
||||
/**
|
||||
* @description 爪子抓到奖品的图片链接
|
||||
*/
|
||||
activeClaw: {
|
||||
type: String,
|
||||
default:
|
||||
'https://img13.360buyimg.com/imagetools/jfs/t1/218082/28/7092/15914/61b088afEf9c253f7/8392e2b14bd8f43a.png',
|
||||
},
|
||||
/**
|
||||
* @description 速度
|
||||
*/
|
||||
speed: makeNumberProp(20),
|
||||
/**
|
||||
* @description 奖品列表
|
||||
*/
|
||||
prizeList: makeArrayProp<any>([]),
|
||||
/**
|
||||
* @description 中奖奖品在列表的索引位置
|
||||
*/
|
||||
prizeIndex: makeNumberProp(-1),
|
||||
}
|
||||
|
||||
export type DollMachineProps = ExtractPropTypes<typeof dollmachineProps>
|
||||
|
||||
export const dollmachineEmits = {
|
||||
[CLICK_EVENT]: () => true,
|
||||
startTurns: () => true,
|
||||
endTurns: () => true,
|
||||
}
|
||||
|
||||
export type DollMachineEmits = typeof dollmachineEmits
|
||||
255
uni_modules/nutui-uni/components/dollmachine/dollmachine.vue
Normal file
255
uni_modules/nutui-uni/components/dollmachine/dollmachine.vue
Normal file
@@ -0,0 +1,255 @@
|
||||
<script setup lang="ts">
|
||||
import type { ComponentInternalInstance } from 'vue'
|
||||
import { computed, defineComponent, getCurrentInstance, onMounted, reactive, ref } from 'vue'
|
||||
import { PREFIX } from '../_constants'
|
||||
import { getMainClass } from '../_utils'
|
||||
import { dollmachineEmits, dollmachineProps } from './dollmachine'
|
||||
|
||||
const props = defineProps(dollmachineProps)
|
||||
|
||||
const emit = defineEmits(dollmachineEmits)
|
||||
const instance = getCurrentInstance() as ComponentInternalInstance
|
||||
const giftPrize = ref()
|
||||
const machineBoxDom = ref()
|
||||
const machineToolsDom = ref()
|
||||
const classes = computed(() => {
|
||||
return getMainClass(props, componentName)
|
||||
})
|
||||
const toolsStyle = reactive({
|
||||
left: '50%',
|
||||
marginLeft: '0',
|
||||
})
|
||||
|
||||
function leftCenter() {
|
||||
toolsStyle.left = '50%'
|
||||
const toolDomW = machineToolsDom.value.width
|
||||
toolsStyle.marginLeft = `-${toolDomW / 2}px`
|
||||
}
|
||||
|
||||
function leftRightMove(flag: string) {
|
||||
const query = uni.createSelectorQuery().in(instance)
|
||||
query.select('.machine-box').boundingClientRect()
|
||||
query.select('.machine-tools').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
machineBoxDom.value = res[0]
|
||||
machineToolsDom.value = res[1]
|
||||
setTimeout(() => {
|
||||
const toolDomLeft = machineToolsDom.value.left
|
||||
const boxDomW = machineBoxDom.value.width
|
||||
const toolDomW = machineToolsDom.value.width
|
||||
const max = boxDomW - toolDomW
|
||||
if (
|
||||
(flag === 'left' && toolDomLeft === 0)
|
||||
|| (flag === 'right' && toolDomLeft === max)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
const distance = flag === 'left' ? -30 : 30
|
||||
const left: number = toolDomLeft + distance
|
||||
|
||||
if (flag === 'left')
|
||||
toolsStyle.left = `${left < 0 ? 0 : left}px`
|
||||
|
||||
else
|
||||
toolsStyle.left = `${left > max ? max : left}px`
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
|
||||
// const topBottomMove = (flag: string) => {
|
||||
// if (flag == "top") {
|
||||
// } else {
|
||||
// }
|
||||
// };
|
||||
|
||||
function moveTools(flag: string) {
|
||||
// toolsStyle.transform = "none";
|
||||
toolsStyle.marginLeft = '0'
|
||||
if (flag === 'left' || flag === 'right') {
|
||||
leftRightMove(flag)
|
||||
}
|
||||
else {
|
||||
// topBottomMove(flag);
|
||||
}
|
||||
}
|
||||
|
||||
const clawStyle = ref({
|
||||
'background-image': `url(${props.defaultClaw})`,
|
||||
'background-size': '100% 100%',
|
||||
'background-position': 'center',
|
||||
'background-repeat': 'no-repeat',
|
||||
})
|
||||
|
||||
const machineRopeDom = ref()
|
||||
const machineClawDom = ref()
|
||||
const machineOperateDom = ref()
|
||||
const machineLock = ref(false)
|
||||
const initLock = ref(false)
|
||||
|
||||
const ropeDomHeight = ref({
|
||||
height: '20px',
|
||||
})
|
||||
|
||||
function startGame() {
|
||||
emit('startTurns')
|
||||
giftPrize.value = ''
|
||||
machineLock.value = true
|
||||
initLock.value = true
|
||||
clawStyle.value['background-image'] = `url(${props.activeClaw})`
|
||||
const heightBox = machineBoxDom.value.height
|
||||
const heightTools = machineToolsDom.value.height
|
||||
const heightOpe = machineOperateDom.value.height
|
||||
ropeDomHeight.value.height = `${heightBox - heightOpe - heightTools - 20}px`
|
||||
}
|
||||
function initGame() {
|
||||
ropeDomHeight.value.height = '20px'
|
||||
}
|
||||
function ropeHeightEnd() {
|
||||
const query = uni.createSelectorQuery().in(instance)
|
||||
query.select('.machine-rope').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
machineRopeDom.value = res[0]
|
||||
initLock.value = false
|
||||
if (machineRopeDom.value.height === 20) {
|
||||
machineLock.value = false
|
||||
emit('endTurns')
|
||||
}
|
||||
clawStyle.value['background-image'] = `url(${props.defaultClaw})`
|
||||
giftPrize.value = props.prizeList[props.prizeIndex].imagePath
|
||||
setTimeout(() => {
|
||||
initGame()
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
const giftEle: any = reactive([])
|
||||
function setGiftEle() {
|
||||
const left = Math.floor(Math.random() * 325)
|
||||
const top = Math.floor(Math.random() * (150 - 70) + 70)
|
||||
const angle = Math.floor(Math.random() * 90)
|
||||
giftEle.push({
|
||||
left: `${left}px`,
|
||||
top: `${top}px`,
|
||||
transform: `rotate(${angle}deg)`,
|
||||
})
|
||||
}
|
||||
|
||||
function init() {
|
||||
giftPrize.value = ''
|
||||
leftCenter()
|
||||
initGame()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
uni.$once('dollMachineMounted', () => {
|
||||
const query = uni.createSelectorQuery().in(instance)
|
||||
query.select('.machine-box').boundingClientRect()
|
||||
query.select('.machine-tools').boundingClientRect()
|
||||
query.select('.machine-operate').boundingClientRect()
|
||||
query.select('.machine-rope').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
machineBoxDom.value = res[0]
|
||||
machineToolsDom.value = res[1]
|
||||
machineOperateDom.value = res[2]
|
||||
machineRopeDom.value = res[3]
|
||||
setTimeout(() => {
|
||||
leftCenter()
|
||||
// ropeHeightEnd()
|
||||
}, 300)
|
||||
})
|
||||
})
|
||||
uni.$emit('dollMachineMounted')
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-doll-machine`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="classes" :style="customClass">
|
||||
<div class="machine-box">
|
||||
<div class="machine-tools" :style="toolsStyle">
|
||||
<div
|
||||
id="machine-rope"
|
||||
class="machine-rope"
|
||||
:style="ropeDomHeight"
|
||||
@transitionend="ropeHeightEnd"
|
||||
@webkitTransitionEnd="ropeHeightEnd"
|
||||
/>
|
||||
<div ref="machineClawDom" class="machine-claw" :style="clawStyle">
|
||||
<image
|
||||
v-if="giftPrize"
|
||||
:src="giftPrize"
|
||||
alt="加载失败"
|
||||
class="gift-prize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="machine-gift-box">
|
||||
<div class="box-glass">
|
||||
<image
|
||||
v-for="(item, index) of prizeList"
|
||||
:id="`gift${index}`"
|
||||
:key="index"
|
||||
:ref="setGiftEle"
|
||||
:src="item.imagePath"
|
||||
class="gift-img"
|
||||
:style="giftEle[index]"
|
||||
@load="setGiftEle"
|
||||
/>
|
||||
</div>
|
||||
<div class="machine-operate">
|
||||
<div
|
||||
class="machine-direction"
|
||||
:class="[machineLock ? 'disabledClick' : '']"
|
||||
>
|
||||
<!-- <span
|
||||
class="direction-block direction-block-top"
|
||||
@click="moveTools('top')"
|
||||
></span> -->
|
||||
<span
|
||||
class="direction-block direction-block-left"
|
||||
@click="moveTools('left')"
|
||||
/>
|
||||
<span
|
||||
class="direction-block direction-block-right"
|
||||
@click="moveTools('right')"
|
||||
/>
|
||||
<!-- <span
|
||||
class="direction-block direction-block-bottom"
|
||||
@click="moveTools('bottom')"
|
||||
></span> -->
|
||||
</div>
|
||||
<div
|
||||
class="machine-btn"
|
||||
:class="[
|
||||
machineLock ? 'machine-disabled disabledClick' : 'machine-start',
|
||||
]"
|
||||
@click="startGame"
|
||||
/>
|
||||
<div
|
||||
class="machine-reset-btn"
|
||||
:class="[initLock ? 'disabledClick' : '']"
|
||||
@click="init"
|
||||
>
|
||||
重置
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
166
uni_modules/nutui-uni/components/dollmachine/index.scss
Normal file
166
uni_modules/nutui-uni/components/dollmachine/index.scss
Normal file
@@ -0,0 +1,166 @@
|
||||
.nut-doll-machine {
|
||||
.machine-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 690px;
|
||||
background: url("https://img12.360buyimg.com/imagetools/jfs/t1/145351/6/24350/800170/61c95470E416c27bb/a3f62a18af70684e.png")
|
||||
no-repeat center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.machine-tools {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all linear 0.3s;
|
||||
}
|
||||
|
||||
.machine-rope {
|
||||
top: 50px;
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
background: linear-gradient(to bottom right, #ff9800, #ffeb3b);
|
||||
transition: all linear 2s;
|
||||
}
|
||||
|
||||
.machine-claw {
|
||||
width: 80px;
|
||||
height: 70px;
|
||||
|
||||
// background: url("https://img14.360buyimg.com/imagetools/jfs/t1/146467/34/22553/4178/61b088afE198f676e/21952e7018d1d141.png")
|
||||
// no-repeat center;
|
||||
// background-size: 100% 100%;
|
||||
text-align: center;
|
||||
|
||||
.gift-prize {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.machine-gift-box {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
// height: 100%;
|
||||
.box-glass {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: #f1d90556;
|
||||
|
||||
.gift-img {
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.machine-operate {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
width: 90%;
|
||||
padding: 5px 20px;
|
||||
margin: 0 auto;
|
||||
|
||||
// position: absolute;
|
||||
// bottom: 0;
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
.machine-direction {
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: url("https://img14.360buyimg.com/imagetools/jfs/t1/3283/2/18965/1403/62c28eb5E0cfb824b/9b90cde1898d18af.png")
|
||||
no-repeat center;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.direction-block {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
|
||||
// background-color: #ff9800;
|
||||
&:nth-child(1) {
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
// &:nth-child(1),
|
||||
// &:nth-child(4) {
|
||||
// display: block;
|
||||
// }
|
||||
// &:nth-child(1) {
|
||||
// top: 0;
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
// }
|
||||
// &:nth-child(2) {
|
||||
// top: 50%;
|
||||
// left: 0;
|
||||
// transform: translateY(-50%);
|
||||
// }
|
||||
// &:nth-child(3) {
|
||||
// top: 50%;
|
||||
// right: 0;
|
||||
// transform: translateY(-50%);
|
||||
// }
|
||||
// &:nth-child(4) {
|
||||
// bottom: 0;
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
.machine-btn {
|
||||
width: 50px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.machine-start {
|
||||
background: url("https://img13.360buyimg.com/imagetools/jfs/t1/205479/17/4245/32041/61309346E02bd3b6b/b41be60bedbb1e69.png")
|
||||
no-repeat center;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.machine-disabled {
|
||||
background: url("https://img10.360buyimg.com/imagetools/jfs/t1/193040/14/21217/16320/61309346E6569e270/36e45126a5f1fc9c.png")
|
||||
no-repeat center;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.machine-reset-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ff9800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stylelint-disable selector-class-pattern
|
||||
|
||||
.disabledClick {
|
||||
pointer-events: none !important;
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
1
uni_modules/nutui-uni/components/dollmachine/index.ts
Normal file
1
uni_modules/nutui-uni/components/dollmachine/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type * from './dollmachine'
|
||||
Reference in New Issue
Block a user